smb-auth-20040711
[openafs.git] / src / WINNT / afsd / smb.c
index 6249535..10e69c5 100644 (file)
@@ -7,10 +7,19 @@
  * directory or online at http://www.openafs.org/dl/license10.html
  */
 
+//#define NOSERVICE 1
+
+#define NOMOREFILESFIX 1
+
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#else
+#include <sys/timeb.h>
+#include <tzfile.h>
+#endif /* !DJGPP */
 #include <stddef.h>
 #include <stdlib.h>
 #include <malloc.h>
 #include <time.h>
 
 #include <osi.h>
+#include <ntstatus.h>
 
 #include "afsd.h"
 
 #include "smb.h"
+#include "lanahelper.h"
 
 /* These characters are illegal in Windows filenames */
 static char *illegalChars = "\\/:*?\"<>|";
@@ -31,10 +42,12 @@ BOOL isWindows2000 = FALSE;
 smb_vc_t *dead_vcp = NULL;
 smb_vc_t *active_vcp = NULL;
 
+/* TODO; logout mechanism needs to be thread-safe */
 char *loggedOutName = NULL;
 smb_user_t *loggedOutUserp = NULL;
 unsigned long loggedOutTime;
 int loggedOut = 0;
+int smbShutdownFlag = 0;
 
 int smb_LogoffTokenTransfer;
 unsigned long smb_LogoffTransferTimeout;
@@ -45,16 +58,19 @@ long ongoingOps = 0;
 
 unsigned int sessionGen = 0;
 
-void afsi_log();
+extern void afsi_log(char *pattern, ...);
+extern HANDLE afsi_file;
 
 osi_hyper_t hzero = {0, 0};
 osi_hyper_t hones = {0xFFFFFFFF, -1};
 
-osi_log_t *smb_logp;
+osi_log_t *  smb_logp;
 osi_rwlock_t smb_globalLock;
 osi_rwlock_t smb_rctLock;
-
-unsigned char smb_LANadapter;
+osi_mutex_t  smb_ListenerLock;
+char smb_LANadapter;
+unsigned char smb_sharename[NCBNAMSZ+1] = {0};
 
 /* for debugging */
 long smb_maxObsConcurrentCalls=0;
@@ -67,23 +83,42 @@ smb_ncb_t *smb_ncbFreeListp;
 
 int smb_NumServerThreads;
 
-int numNCBs, numSessions;
+int numNCBs, numSessions, numVCs;
 
-#define NCBmax 100
-HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
-HANDLE **NCBreturns;
+int smb_maxVCPerServer;
+int smb_maxMpxRequests;
+
+int smb_authType = SMB_AUTH_EXTENDED; /* type of SMB auth to use. One of SMB_AUTH_* */
+HANDLE smb_lsaHandle;
+ULONG smb_lsaSecPackage;
+LSA_STRING smb_lsaLogonOrigin;
+
+#define NCBmax MAXIMUM_WAIT_OBJECTS
+EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
+EVENT_HANDLE **NCBreturns;
 DWORD NCBsessions[NCBmax];
 NCB *NCBs[NCBmax];
 struct smb_packet *bufs[NCBmax];
 
-#define Sessionmax 100
-HANDLE SessionEvents[Sessionmax];
+#define Sessionmax MAXIMUM_WAIT_OBJECTS
+EVENT_HANDLE SessionEvents[Sessionmax];
 unsigned short LSNs[Sessionmax];
+int lanas[Sessionmax];
 BOOL dead_sessions[Sessionmax];
+LANA_ENUM lana_list;
 
 /* for raw I/O */
 osi_mutex_t smb_RawBufLock;
+#ifdef DJGPP
+#define SMB_RAW_BUFS 4
+dos_ptr smb_RawBufs;
+int smb_RawBufSel[SMB_RAW_BUFS];
+#else
 char *smb_RawBufs;
+#endif /* DJGPP */
+
+#define SMB_MASKFLAG_TILDE 1
+#define SMB_MASKFLAG_CASEFOLD 2
 
 #define RAWTIMEOUT INFINITE
 
@@ -92,7 +127,11 @@ typedef struct raw_write_cont {
        long code;
        osi_hyper_t offset;
        long count;
+#ifndef DJGPP
        char *buf;
+#else
+       dos_ptr buf;
+#endif /* DJGPP */
        int writeMode;
        long alreadyWritten;
 } raw_write_cont_t;
@@ -102,11 +141,18 @@ long smb_dirSearchCounter = 1;
 smb_dirSearch_t *smb_firstDirSearchp;
 smb_dirSearch_t *smb_lastDirSearchp;
 
+/* hide dot files? */
+int smb_hideDotFiles;
+
 /* global state about V3 protocols */
 int smb_useV3;         /* try to negotiate V3 */
 
+#ifndef DJGPP
+static showErrors = 1;
 /* MessageBox or something like it */
-int (WINAPI *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
+int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
+extern HANDLE WaitToTerminate;
+#endif /* DJGPP */
 
 /* GMT time info:
  * Time in Unix format of midnight, 1/1/1970 local time.
@@ -117,15 +163,44 @@ long smb_localZero;
 /* Time difference for converting to kludge-GMT */
 int smb_NowTZ;
 
-char *smb_localNamep;
+char *smb_localNamep = NULL;
 
 smb_vc_t *smb_allVCsp;
 
+smb_username_t *usernamesp = NULL;
+
 smb_waitingLock_t *smb_allWaitingLocks;
 
 /* forward decl */
 void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
-       NCB *ncbp, raw_write_cont_t *rwcp);
+                                               NCB *ncbp, raw_write_cont_t *rwcp);
+void smb_NetbiosInit();
+#ifdef DJGPP
+#ifndef AFS_WIN95_ENV
+DWORD smb_ServerExceptionFilter(void);
+#endif
+
+extern char cm_HostName[];
+extern char cm_confDir[];
+#endif
+
+#ifdef DJGPP
+#define LPTSTR char *
+#define GetComputerName(str, sizep) \
+       strcpy((str), cm_HostName); \
+       *(sizep) = strlen(cm_HostName)
+#endif /* DJGPP */
+
+extern char AFSConfigKeyName[];
+
+char smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = ""; /* domain name */
+int smb_ServerDomainNameLength = 0;
+char smb_ServerOS[] = "Windows 5.0"; /* Faux OS String */
+int smb_ServerOSLength = sizeof(smb_ServerOS);
+char smb_ServerLanManager[] = "Windows 2000 LAN Manager"; /* Faux LAN Manager string */
+int smb_ServerLanManagerLength = sizeof(smb_ServerLanManager);
+
+GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
 
 /*
  * Demo expiration
@@ -137,7 +212,145 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
 #define EXPIREDATE 834000000           /* Wed Jun 5 1996 */
 
 
+char * myCrt_Dispatch(int i)
+{
+       switch (i)
+       {
+       default:
+               return "unknown SMB op";
+       case 0x00:
+               return "(00)ReceiveCoreMakeDir";
+       case 0x01:
+               return "(01)ReceiveCoreRemoveDir";
+       case 0x02:
+               return "(02)ReceiveCoreOpen";
+       case 0x03:
+               return "(03)ReceiveCoreCreate";
+       case 0x04:
+               return "(04)ReceiveCoreClose";
+       case 0x05:
+               return "(05)ReceiveCoreFlush";
+       case 0x06:
+               return "(06)ReceiveCoreUnlink";
+       case 0x07:
+               return "(07)ReceiveCoreRename";
+       case 0x08:
+               return "(08)ReceiveCoreGetFileAttributes";
+       case 0x09:
+               return "(09)ReceiveCoreSetFileAttributes";
+       case 0x0a:
+               return "(0a)ReceiveCoreRead";
+       case 0x0b:
+               return "(0b)ReceiveCoreWrite";
+       case 0x0c:
+               return "(0c)ReceiveCoreLockRecord";
+       case 0x0d:
+               return "(0d)ReceiveCoreUnlockRecord";
+       case 0x0e:
+               return "(0e)SendCoreBadOp";
+       case 0x0f:
+               return "(0f)ReceiveCoreCreate";
+       case 0x10:
+               return "(10)ReceiveCoreCheckPath";
+       case 0x11:
+               return "(11)SendCoreBadOp";
+       case 0x12:
+               return "(12)ReceiveCoreSeek";
+       case 0x1a:
+               return "(1a)ReceiveCoreReadRaw";
+       case 0x1d:
+               return "(1d)ReceiveCoreWriteRawDummy";
+       case 0x22:
+               return "(22)ReceiveV3SetAttributes";
+       case 0x23:
+               return "(23)ReceiveV3GetAttributes";
+       case 0x24:
+               return "(24)ReceiveV3LockingX";
+       case 0x29:
+               return "(29)SendCoreBadOp";
+       case 0x2b:
+               return "(2b)ReceiveCoreEcho";
+       case 0x2d:
+               return "(2d)ReceiveV3OpenX";
+       case 0x2e:
+               return "(2e)ReceiveV3ReadX";
+       case 0x32:
+               return "(32)ReceiveV3Tran2A";
+       case 0x33:
+               return "(33)ReceiveV3Tran2A";
+       case 0x34:
+               return "(34)ReceiveV3FindClose";
+       case 0x35:
+               return "(35)ReceiveV3FindNotifyClose";
+       case 0x70:
+               return "(70)ReceiveCoreTreeConnect";
+       case 0x71:
+               return "(71)ReceiveCoreTreeDisconnect";
+       case 0x72:
+               return "(72)ReceiveNegotiate";
+       case 0x73:
+               return "(73)ReceiveV3SessionSetupX";
+       case 0x74:
+               return "(74)ReceiveV3UserLogoffX";
+       case 0x75:
+               return "(75)ReceiveV3TreeConnectX";
+       case 0x80:
+               return "(80)ReceiveCoreGetDiskAttributes";
+       case 0x81:
+               return "(81)ReceiveCoreSearchDir";
+       case 0xA0:
+               return "(A0)ReceiveNTTransact";
+       case 0xA2:
+               return "(A2)ReceiveNTCreateX";
+       case 0xA4:
+               return "(A4)ReceiveNTCancel";
+       case 0xc0:
+               return "(c0)SendCoreBadOp";
+       case 0xc1:
+               return "(c1)SendCoreBadOp";
+       case 0xc2:
+               return "(c2)SendCoreBadOp";
+       case 0xc3:
+               return "(c3)SendCoreBadOp";
+       }
+}
 
+char * myCrt_2Dispatch(int i)
+{
+       switch (i)
+       {
+       default:
+               return "unknown SMB op-2";
+       case 0:
+               return "S(00)CreateFile";
+       case 1:
+               return "S(01)FindFirst";
+       case 2:
+               return "S(02)FindNext"; /* FindNext */
+       case 3:
+               return "S(03)QueryFileSystem_ReceiveTran2QFSInfo";
+       case 4:
+               return "S(04)??";
+       case 5:
+               return "S(05)QueryFileInfo_ReceiveTran2QPathInfo";
+       case 6:
+               return "S(06)SetFileInfo_ReceiveTran2SetPathInfo";
+       case 7:
+               return "S(07)SetInfoHandle_ReceiveTran2QFileInfo";
+       case 8:
+               return "S(08)??_ReceiveTran2SetFileInfo";
+       case 9:
+               return "S(09)??_ReceiveTran2FSCTL";
+       case 10:
+               return "S(0a)_ReceiveTran2IOCTL";
+       case 11:
+               return "S(0b)_ReceiveTran2FindNotifyFirst";
+       case 12:
+               return "S(0c)_ReceiveTran2FindNotifyNext";
+       case 13:
+               return "S(0d)CreateDirectory_ReceiveTran2MKDir";
+       }
+}
 
 /* scache must be locked */
 unsigned int smb_Attributes(cm_scache_t *scp)
@@ -145,10 +358,10 @@ unsigned int smb_Attributes(cm_scache_t *scp)
        unsigned int attrs;
 
        if (scp->fileType == CM_SCACHETYPE_DIRECTORY
-               || scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
-                       attrs = 0x10;
+               || scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+               attrs = SMB_ATTR_DIRECTORY;
        else
-               attrs = 0;
+               attrs = 0;
 
        /*
         * We used to mark a file RO if it was in an RO volume, but that
@@ -158,50 +371,75 @@ unsigned int smb_Attributes(cm_scache_t *scp)
        if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
 #endif
        if ((scp->unixModeBits & 0222) == 0)
-               attrs |= 1;     /* turn on read-only flag */
+               attrs |= SMB_ATTR_READONLY;     /* turn on read-only flag */
 
        return attrs;
 }
 
+/* Check if the named file/dir is a dotfile/dotdir */
+/* String pointed to by lastComp can have leading slashes, but otherwise should have
+   no other patch components */
+unsigned int smb_IsDotFile(char *lastComp) {
+       char *s;
+       if(lastComp) {
+               /* skip over slashes */
+        for(s=lastComp;*s && (*s == '\\' || *s == '/'); s++);
+       }
+       else
+               return 0;
+
+    /* nulls, curdir and parent dir doesn't count */
+       if(!*s) return 0;
+       if(*s == '.') {
+               if(!*(s + 1)) return 0;
+               if(*(s+1) == '.' && !*(s + 2)) return 0;
+               return 1;
+       }
+       return 0;
+}
+
 static int ExtractBits(WORD bits, short start, short len)
 {
-        int end;
-        WORD num;
+       int end;
+       WORD num;
 
-        end = start + len;
-        
-        num = bits << (16 - end);
-        num = num >> ((16 - end) + start);
+       end = start + len;
         
-        return (int)num;
+       num = bits << (16 - end);
+       num = num >> ((16 - end) + start);
+
+       return (int)num;
 }
 
+#ifndef DJGPP
 void ShowUnixTime(char *FuncName, long unixTime)
 {
-        FILETIME ft;
-        WORD wDate, wTime;
+       FILETIME ft;
+       WORD wDate, wTime;
 
        smb_LargeSearchTimeFromUnixTime(&ft, unixTime);
                 
-        if (!FileTimeToDosDateTime(&ft, &wDate, &wTime))
-                osi_Log1(afsd_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
-        else {
-                int day, month, year, sec, min, hour;
-                char msg[256];
-                
-                day = ExtractBits(wDate, 0, 5);
-                month = ExtractBits(wDate, 5, 4);
-                year = ExtractBits(wDate, 9, 7) + 1980;
-                
-                sec = ExtractBits(wTime, 0, 5);
-                min = ExtractBits(wTime, 5, 6);
-                hour = ExtractBits(wTime, 11, 5);
-                
-                sprintf(msg, "%s = %02d-%02d-%04d %02d:%02d:%02d", FuncName, month, day, year, hour, min, sec);
-                osi_Log1(afsd_logp, "%s", osi_LogSaveString(afsd_logp, msg));
-        }
+       if (!FileTimeToDosDateTime(&ft, &wDate, &wTime))
+               osi_Log1(smb_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
+       else {
+               int day, month, year, sec, min, hour;
+               char msg[256];
+
+               day = ExtractBits(wDate, 0, 5);
+               month = ExtractBits(wDate, 5, 4);
+               year = ExtractBits(wDate, 9, 7) + 1980;
+
+               sec = ExtractBits(wTime, 0, 5);
+               min = ExtractBits(wTime, 5, 6);
+               hour = ExtractBits(wTime, 11, 5);
+
+               sprintf(msg, "%s = %02d-%02d-%04d %02d:%02d:%02d", FuncName, month, day, year, hour, min, sec);
+               osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, msg));
+       }
 }
+#endif /* DJGPP */
 
+#ifndef DJGPP
 /* Determine if we are observing daylight savings time */
 void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
 {
@@ -211,13 +449,13 @@ void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
        /* Get the time zone info. NT uses this to calc if we are in DST. */
        GetTimeZoneInformation(&timeZoneInformation);
  
-        /* Return the daylight bias */
-        *pDstBias = timeZoneInformation.DaylightBias;
+       /* Return the daylight bias */
+       *pDstBias = timeZoneInformation.DaylightBias;
 
-        /* Return the bias */
-        *pBias = timeZoneInformation.Bias;
+       /* Return the bias */
+       *pBias = timeZoneInformation.Bias;
 
-        /* Now determine if DST is being observed */
+       /* Now determine if DST is being observed */
 
        /* Get the UTC (GMT) time */
        GetSystemTime(&utc);
@@ -244,42 +482,55 @@ void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
        */
        *pDST = localDST.wHour != local.wHour;
 }
+#else
+/* Determine if we are observing daylight savings time */
+void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
+{
+       struct timeb t;
+
+       ftime(&t);
+       *pDST = t.dstflag;
+       *pDstBias = -60;    /* where can this be different? */
+       *pBias = t.timezone;
+}
+#endif /* DJGPP */
 
 void CompensateForSmbClientLastWriteTimeBugs(long *pLastWriteTime)
 {
-        BOOL dst;       /* Will be TRUE if observing DST */
-        LONG dstBias;   /* Offset from local time if observing DST */
-        LONG bias;      /* Offset from GMT for local time */
-        
-        /*
-         * This function will adjust the last write time to compensate
-         * for two bugs in the smb client:
-         *
-         *    1) During Daylight Savings Time, the LastWriteTime is ahead
-         *       in time by the DaylightBias (ignoring the sign - the
-         *       DaylightBias is always stored as a negative number).  If
-         *       the DaylightBias is -60, then the LastWriteTime will be
-         *       ahead by 60 minutes.
-         *
-         *    2) If the local time zone is a positive offset from GMT, then
-         *       the LastWriteTime will be the correct local time plus the
-         *       Bias (ignoring the sign - a positive offset from GMT is
-         *       always stored as a negative Bias).  If the Bias is -120,
-         *       then the LastWriteTime will be ahead by 120 minutes.
-         *
-         *    These bugs can occur at the same time.
-         */
+       BOOL dst;       /* Will be TRUE if observing DST */
+       LONG dstBias;   /* Offset from local time if observing DST */
+       LONG bias;      /* Offset from GMT for local time */
 
-        GetTimeZoneInfo(&dst, &dstBias, &bias);
-         
-         /* First adjust for DST */
-        if (dst)
-               *pLastWriteTime -= (-dstBias * 60);     /* Convert dstBias to seconds */
-               
-        /* Now adjust for a positive offset from GMT (a negative bias). */
-        if (bias < 0)
-                *pLastWriteTime -= (-bias * 60);        /* Convert bias to seconds */
-}
+       /*
+        * This function will adjust the last write time to compensate
+        * for two bugs in the smb client:
+        *
+        *    1) During Daylight Savings Time, the LastWriteTime is ahead
+        *       in time by the DaylightBias (ignoring the sign - the
+        *       DaylightBias is always stored as a negative number).  If
+        *       the DaylightBias is -60, then the LastWriteTime will be
+        *       ahead by 60 minutes.
+        *
+        *    2) If the local time zone is a positive offset from GMT, then
+        *       the LastWriteTime will be the correct local time plus the
+        *       Bias (ignoring the sign - a positive offset from GMT is
+        *       always stored as a negative Bias).  If the Bias is -120,
+        *       then the LastWriteTime will be ahead by 120 minutes.
+        *
+        *    These bugs can occur at the same time.
+        */
+
+       GetTimeZoneInfo(&dst, &dstBias, &bias);
+
+       /* First adjust for DST */
+       if (dst)
+               *pLastWriteTime -= (-dstBias * 60);     /* Convert dstBias to seconds */
+
+       /* Now adjust for a positive offset from GMT (a negative bias). */
+       if (bias < 0)
+               *pLastWriteTime -= (-bias * 60);        /* Convert bias to seconds */
+}              
 
 /*
  * Calculate the difference (in seconds) between local time and GMT.
@@ -297,12 +548,21 @@ smb_CalculateNowTZ()
        local_tm = *(localtime(&t));
 
        days = local_tm.tm_yday - gmt_tm.tm_yday;
-       hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour;
+       hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour
+#ifdef COMMENT
+        /* There is a problem with DST immediately after the time change
+         * which may continue to exist until the machine is rebooted
+         */
+        - (local_tm.tm_isdst ? 1 : 0)
+#endif /* COMMENT */
+        ;
        minutes = 60 * hours + local_tm.tm_min - gmt_tm.tm_min;
        seconds = 60 * minutes + local_tm.tm_sec - gmt_tm.tm_sec;
 
        smb_NowTZ = seconds;
 }
+
+#ifndef DJGPP
 void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, long unixTime)
 {
        struct tm *ltp;
@@ -342,7 +602,29 @@ void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, long unixTime)
 
        SystemTimeToFileTime(&stm, largeTimep);
 }
+#else /* DJGPP */
+void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, long unixTime)
+{
+       /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
+       /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 ??? */
+       LARGE_INTEGER *ft = (LARGE_INTEGER *) largeTimep;
+       LARGE_INTEGER ut;
+       int leap_years = 89;   /* leap years betw 1/1/1601 and 1/1/1970 */
+
+       /* set ft to number of 100ns intervals betw 1/1/1601 and 1/1/1970 GMT */
+       *ft = ConvertLongToLargeInteger(((EPOCH_YEAR-1601) * 365 + leap_years)
+                                   * 24 * 60);
+       *ft = LargeIntegerMultiplyByLong(*ft, 60);
+       *ft = LargeIntegerMultiplyByLong(*ft, 10000000);
+
+       /* add unix time */
+       ut = ConvertLongToLargeInteger(unixTime);
+       ut = LargeIntegerMultiplyByLong(ut, 10000000);
+       *ft = LargeIntegerAdd(*ft, ut);
+}
+#endif /* !DJGPP */
 
+#ifndef DJGPP
 void smb_UnixTimeFromLargeSearchTime(long *unixTimep, FILETIME *largeTimep)
 {
        SYSTEMTIME stm;
@@ -365,50 +647,71 @@ void smb_UnixTimeFromLargeSearchTime(long *unixTimep, FILETIME *largeTimep)
        *unixTimep = mktime(&lt);
        _timezone = save_timezone;
 }
+#else /* DJGPP */
+void smb_UnixTimeFromLargeSearchTime(long *unixTimep, FILETIME *largeTimep)
+{
+       /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
+       /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 GMT? */
+       LARGE_INTEGER *ft = (LARGE_INTEGER *) largeTimep;
+       LARGE_INTEGER a;
+       int leap_years = 89;
+
+       /* set to number of 100ns intervals betw 1/1/1601 and 1/1/1970 */
+       a = ConvertLongToLargeInteger(((EPOCH_YEAR-1601) * 365 + leap_years) * 24 * 60);
+       a = LargeIntegerMultiplyByLong(a, 60);
+       a = LargeIntegerMultiplyByLong(a, 10000000);
+
+       /* subtract it from ft */
+       a = LargeIntegerSubtract(*ft, a);
+
+       /* divide down to seconds */
+       *unixTimep = LargeIntegerDivideByLong(a, 10000000);
+}
+#endif /* !DJGPP */
 
 void smb_SearchTimeFromUnixTime(long *dosTimep, long unixTime)
 {
        struct tm *ltp;
-        int dosDate;
-        int dosTime;
-        struct tm localJunk;
+       int dosDate;
+       int dosTime;
+       struct tm localJunk;
 
-       ltp = localtime(&unixTime);
+       ltp = localtime((time_t*) &unixTime);
 
        /* if we fail, make up something */
-        if (!ltp) {
+       if (!ltp) {
                ltp = &localJunk;
-                localJunk.tm_year = 89 - 20;
-                localJunk.tm_mon = 4;
-                localJunk.tm_mday = 12;
-                localJunk.tm_hour = 0;
-                localJunk.tm_min = 0;
-                localJunk.tm_sec = 0;
-       }
+               localJunk.tm_year = 89 - 20;
+               localJunk.tm_mon = 4;
+               localJunk.tm_mday = 12;
+               localJunk.tm_hour = 0;
+               localJunk.tm_min = 0;
+               localJunk.tm_sec = 0;
+       }       
 
        dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
-        dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
-        *dosTimep = (dosDate<<16) | dosTime;
-}
+       dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
+       *dosTimep = (dosDate<<16) | dosTime;
+}      
 
 void smb_UnixTimeFromSearchTime(long *unixTimep, long searchTime)
 {
        unsigned short dosDate;
-        unsigned short dosTime;
+       unsigned short dosTime;
        struct tm localTm;
         
-        dosDate = searchTime & 0xffff;
-        dosTime = (searchTime >> 16) & 0xffff;
-        
-        localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
-        localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1;   /* January is 0 in localTm */
-        localTm.tm_mday = (dosDate) & 0x1f;
-        localTm.tm_hour = (dosTime>>11) & 0x1f;
-        localTm.tm_min = (dosTime >> 5) & 0x3f;
-        localTm.tm_sec = (dosTime & 0x1f) * 2;
-        localTm.tm_isdst = -1;                         /* compute whether DST in effect */
+       dosDate = searchTime & 0xffff;
+       dosTime = (searchTime >> 16) & 0xffff;
         
-        *unixTimep = mktime(&localTm);
+       localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
+       localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1;    /* January is 0 in localTm */
+       localTm.tm_mday = (dosDate) & 0x1f;
+       localTm.tm_hour = (dosTime>>11) & 0x1f;
+       localTm.tm_min = (dosTime >> 5) & 0x3f;
+       localTm.tm_sec = (dosTime & 0x1f) * 2;
+       localTm.tm_isdst = -1;                          /* compute whether DST in effect */
+
+       *unixTimep = mktime(&localTm);
 }
 
 void smb_DosUTimeFromUnixTime(long *dosUTimep, long unixTime)
@@ -418,45 +721,80 @@ void smb_DosUTimeFromUnixTime(long *dosUTimep, long unixTime)
 
 void smb_UnixTimeFromDosUTime(long *unixTimep, long dosTime)
 {
+#ifndef DJGPP
        *unixTimep = dosTime + smb_localZero;
+#else /* DJGPP */
+       /* dosTime seems to be already adjusted for GMT */
+       *unixTimep = dosTime;
+#endif /* !DJGPP */
 }
 
-smb_vc_t *smb_FindVC(unsigned short lsn, int flags)
+smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
 {
        smb_vc_t *vcp;
 
        lock_ObtainWrite(&smb_rctLock);
        for(vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
-               if (lsn == vcp->lsn) {
+               if (lsn == vcp->lsn && lana == vcp->lana) {
                        vcp->refCount++;
-                       break;
+                       break;
                }
-        }
-        if (!vcp && (flags & SMB_FLAG_CREATE)) {
+       }
+       if (!vcp && (flags & SMB_FLAG_CREATE)) {
                vcp = malloc(sizeof(*vcp));
-                memset(vcp, 0, sizeof(*vcp));
-                vcp->refCount = 1;
-                vcp->tidCounter = 1;
-                vcp->fidCounter = 1;
-                vcp->nextp = smb_allVCsp;
-                smb_allVCsp = vcp;
-                lock_InitializeMutex(&vcp->mx, "vc_t mutex");
-                vcp->lsn = lsn;
-        }
-        lock_ReleaseWrite(&smb_rctLock);
-        return vcp;
+               memset(vcp, 0, sizeof(*vcp));
+        vcp->vcID = numVCs++;
+               vcp->refCount = 1;
+               vcp->tidCounter = 1;
+               vcp->fidCounter = 1;
+               vcp->uidCounter = 1;  /* UID 0 is reserved for blank user */
+               vcp->nextp = smb_allVCsp;
+               smb_allVCsp = vcp;
+               lock_InitializeMutex(&vcp->mx, "vc_t mutex");
+               vcp->lsn = lsn;
+               vcp->lana = lana;
+        vcp->secCtx = NULL;
+
+               if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
+            /* We must obtain a challenge for extended auth 
+             * in case the client negotiates smb v3 
+             */
+            NTSTATUS nts,ntsEx;
+                       MSV1_0_LM20_CHALLENGE_REQUEST lsaReq;
+                       PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp;
+                       ULONG lsaRespSize;
+
+                       lsaReq.MessageType = MsV1_0Lm20ChallengeRequest;
+
+                       nts = LsaCallAuthenticationPackage( smb_lsaHandle,
+                                                smb_lsaSecPackage,
+                                                &lsaReq,
+                                                sizeof(lsaReq),
+                                                &lsaResp,
+                                                &lsaRespSize,
+                                                &ntsEx);
+                       osi_assert(nts == STATUS_SUCCESS); /* this had better work! */
+
+                       memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
+            LsaFreeReturnBuffer(lsaResp);
+               }
+               else
+                       memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
+       }
+       lock_ReleaseWrite(&smb_rctLock);
+       return vcp;
 }
 
 int smb_IsStarMask(char *maskp)
 {
        int i;
-        char tc;
+       char tc;
         
        for(i=0; i<11; i++) {
                tc = *maskp++;
-                if (tc == '?' || tc == '*' || tc == '>') return 1;        
-       }
-        return 0;
+               if (tc == '?' || tc == '*' || tc == '>') return 1;        
+       }       
+       return 0;
 }
 
 void smb_ReleaseVC(smb_vc_t *vcp)
@@ -481,98 +819,162 @@ smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
        for(tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
                if (tid == tidp->tid) {
                        tidp->refCount++;
-                       break;
-               }
-        }
-        if (!tidp && (flags & SMB_FLAG_CREATE)) {
+                       break;
+               }       
+       }
+       if (!tidp && (flags & SMB_FLAG_CREATE)) {
                tidp = malloc(sizeof(*tidp));
-                memset(tidp, 0, sizeof(*tidp));
-                tidp->nextp = vcp->tidsp;
-                tidp->refCount = 1;
-                tidp->vcp = vcp;
-                vcp->tidsp = tidp;
-                lock_InitializeMutex(&tidp->mx, "tid_t mutex");
-                tidp->tid = tid;
-        }
-        lock_ReleaseWrite(&smb_rctLock);
-        return tidp;
-}
+               memset(tidp, 0, sizeof(*tidp));
+               tidp->nextp = vcp->tidsp;
+               tidp->refCount = 1;
+               tidp->vcp = vcp;
+        vcp->refCount++;
+               vcp->tidsp = tidp;
+               lock_InitializeMutex(&tidp->mx, "tid_t mutex");
+               tidp->tid = tid;
+       }
+       lock_ReleaseWrite(&smb_rctLock);
+       return tidp;
+}      
 
 void smb_ReleaseTID(smb_tid_t *tidp)
 {
        smb_tid_t *tp;
-        smb_tid_t **ltpp;
-        cm_user_t *userp;
+       smb_tid_t **ltpp;
+       cm_user_t *userp;
+    smb_vc_t  *vcp;
 
        userp = NULL;
+    vcp = NULL;
        lock_ObtainWrite(&smb_rctLock);
        osi_assert(tidp->refCount-- > 0);
-        if (tidp->refCount == 0 && (tidp->flags & SMB_TIDFLAG_DELETE)) {
+       if (tidp->refCount == 0 && (tidp->flags & SMB_TIDFLAG_DELETE)) {
                ltpp = &tidp->vcp->tidsp;
                for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
                        if (tp == tidp) break;
-                }
-                osi_assert(tp != NULL);
-                *ltpp = tp->nextp;
-                lock_FinalizeMutex(&tidp->mx);
-                userp = tidp->userp;   /* remember to drop ref later */
-        }
-       lock_ReleaseWrite(&smb_rctLock);
-        if (userp) {
-               cm_ReleaseUser(userp);
+               }
+               osi_assert(tp != NULL);
+               *ltpp = tp->nextp;
+               lock_FinalizeMutex(&tidp->mx);
+               userp = tidp->userp;    /* remember to drop ref later */
+        vcp = tidp->vcp;
        }
-}
+       lock_ReleaseWrite(&smb_rctLock);
+       if (userp) {
+               cm_ReleaseUser(userp);
+       }       
+    if (vcp) {
+        smb_ReleaseVC(vcp);
+    }
+}      
 
 smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
 {
-       smb_user_t *uidp;
+       smb_user_t *uidp = NULL;
 
        lock_ObtainWrite(&smb_rctLock);
        for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
                if (uid == uidp->userID) {
                        uidp->refCount++;
-                       break;
+                       osi_LogEvent("AFS smb_FindUID (Find by UID)",NULL," VCP[%x] found-uid[%d] name[%s]",(int)vcp,uidp->userID,(uidp->unp) ? uidp->unp->name : "");
+               break;
                }
-        }
-        if (!uidp && (flags & SMB_FLAG_CREATE)) {
+       }
+       if (!uidp && (flags & SMB_FLAG_CREATE)) {
                uidp = malloc(sizeof(*uidp));
-                memset(uidp, 0, sizeof(*uidp));
-                uidp->nextp = vcp->usersp;
-                uidp->refCount = 1;
-                uidp->vcp = vcp;
-                vcp->usersp = uidp;
-                lock_InitializeMutex(&uidp->mx, "uid_t mutex");
-                uidp->userID = uid;
-        }
-        lock_ReleaseWrite(&smb_rctLock);
-        return uidp;
-}
+               memset(uidp, 0, sizeof(*uidp));
+               uidp->nextp = vcp->usersp;
+               uidp->refCount = 1;
+               uidp->vcp = vcp;
+        vcp->refCount++;
+               vcp->usersp = uidp;
+               lock_InitializeMutex(&uidp->mx, "user_t mutex");
+               uidp->userID = uid;
+               osi_LogEvent("AFS smb_FindUID (Find by UID)",NULL,"VCP[%x] new-uid[%d] name[%s]",(int)vcp,uidp->userID,(uidp->unp ? uidp->unp->name : ""));
+       }
+       lock_ReleaseWrite(&smb_rctLock);
+       return uidp;
+}      
+
+smb_username_t *smb_FindUserByName(char *usern, char *machine, int flags)
+{
+       smb_username_t *unp= NULL;
+
+       lock_ObtainWrite(&smb_rctLock);
+       for(unp = usernamesp; unp; unp = unp->nextp) {
+               if (stricmp(unp->name, usern) == 0 &&
+                       stricmp(unp->machine, machine) == 0) {
+                       unp->refCount++;
+                       break;
+               }
+       }
+       if (!unp && (flags & SMB_FLAG_CREATE)) {
+               unp = malloc(sizeof(*unp));
+               memset(unp, 0, sizeof(*unp));
+               unp->refCount = 1;
+               unp->nextp = usernamesp;
+               unp->name = strdup(usern);
+               unp->machine = strdup(machine);
+               usernamesp = unp;
+               lock_InitializeMutex(&unp->mx, "username_t mutex");
+       }
+       lock_ReleaseWrite(&smb_rctLock);
+       return unp;
+}      
+
+smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern)
+{
+       smb_user_t *uidp= NULL;
 
+       lock_ObtainWrite(&smb_rctLock);
+       for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
+               if (!uidp->unp) 
+            continue;
+               if (stricmp(uidp->unp->name, usern) == 0) {
+            uidp->refCount++;
+                       osi_LogEvent("AFS smb_FindUserByNameThisSession",NULL,"VCP[%x] uid[%d] match-name[%s]",(int)vcp,uidp->userID,usern);
+            break;
+               } else
+            continue;
+       }       
+       lock_ReleaseWrite(&smb_rctLock);
+       return uidp;
+}
 void smb_ReleaseUID(smb_user_t *uidp)
 {
        smb_user_t *up;
-        smb_user_t **lupp;
-        cm_user_t *userp;
+       smb_user_t **lupp;
+       cm_user_t *userp;
+    smb_vc_t  *vcp;
 
        userp = NULL;
+    vcp = NULL;
        lock_ObtainWrite(&smb_rctLock);
        osi_assert(uidp->refCount-- > 0);
-        if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) {
+       if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) {
                lupp = &uidp->vcp->usersp;
                for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
                        if (up == uidp) break;
-                }
-                osi_assert(up != NULL);
-                *lupp = up->nextp;
-                lock_FinalizeMutex(&uidp->mx);
-                userp = uidp->userp;   /* remember to drop ref later */
+               }
+               osi_assert(up != NULL);
+               *lupp = up->nextp;
+               lock_FinalizeMutex(&uidp->mx);
+               if (uidp->unp) {
+                       userp = uidp->unp->userp;       /* remember to drop ref later */
+            uidp->unp->userp = NULL;
         }
+        vcp = uidp->vcp;
+        uidp->vcp = NULL;
+       }               
        lock_ReleaseWrite(&smb_rctLock);
-        if (userp) {
+       if (userp) {
                cm_ReleaseUserVCRef(userp);
-               cm_ReleaseUser(userp);
-       }
-}
+               cm_ReleaseUser(userp);
+       }       
+    if (vcp) {
+        smb_ReleaseVC(vcp);
+    }
+}      
 
 /* retrieve a held reference to a user structure corresponding to an incoming
  * request.
@@ -581,21 +983,22 @@ void smb_ReleaseUID(smb_user_t *uidp)
 cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp)
 {
        smb_user_t *uidp;
-        cm_user_t *up;
-        smb_t *smbp;
-        
+       cm_user_t *up;
+       smb_t *smbp;
+
        smbp = (smb_t *) inp;
-        uidp = smb_FindUID(vcp, smbp->uid, 0);
-        if (!uidp) return NULL;
+       uidp = smb_FindUID(vcp, smbp->uid, 0);
+       if ((!uidp) ||  (!uidp->unp))
+               return NULL;
         
        lock_ObtainMutex(&uidp->mx);
-        up = uidp->userp;
-        cm_HoldUser(up);
+       up = uidp->unp->userp;
+       cm_HoldUser(up);
        lock_ReleaseMutex(&uidp->mx);
 
-        smb_ReleaseUID(uidp);
+       smb_ReleaseUID(uidp);
         
-        return up;
+       return up;
 }
 
 /*
@@ -608,6 +1011,8 @@ char *smb_GetTIDPath(smb_vc_t *vcp, unsigned short tid)
        char *tpath;
 
        tidp = smb_FindTID(vcp, tid, 0);
+    if (!tidp) 
+        return NULL;
        tpath = tidp->pathname;
        smb_ReleaseTID(tidp);
        return tpath;
@@ -620,8 +1025,10 @@ char *smb_GetTIDPath(smb_vc_t *vcp, unsigned short tid)
  */
 int smb_ChainFID(int fid, smb_packet_t *inp)
 {
-       if (inp->fid == 0 || inp->inCount == 0) return fid;
-        else return inp->fid;
+       if (inp->fid == 0 || inp->inCount == 0) 
+               return fid;
+       else 
+               return inp->fid;
 }
 
 /* are we a priv'd user?  What does this mean on NT? */
@@ -630,82 +1037,110 @@ int smb_SUser(cm_user_t *userp)
        return 1;
 }
 
-/* find a file ID.  If pass in 0, we'll allocate on on a create operation. */
+/* find a file ID.  If we pass in 0 we select an used File ID.
+ * If the SMB_FLAG_CREATE flag is set, we allocate a new  
+ * smb_fid_t data structure if desired File ID cannot be found.
+ */
 smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
 {
        smb_fid_t *fidp;
-       int newFid;
+       int newFid = 0;
         
+    if (fid == 0 && !(flags & SMB_FLAG_CREATE))
+        return NULL;
+
+       lock_ObtainWrite(&smb_rctLock);
        /* figure out if we need to allocate a new file ID */
-        if (fid == 0) {
-               newFid = 1;
-                fid = vcp->fidCounter;
+       if (fid == 0) {
+               newFid = 1;
+               fid = vcp->fidCounter;
        }
-        else newFid = 0;
 
-       lock_ObtainWrite(&smb_rctLock);
 retry:
        for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
                if (fid == fidp->fid) {
                        if (newFid) {
                                fid++;
-                                if (fid == 0) fid = 1;
-                                goto retry;
-                        }
+                if (fid == 0) 
+                                       fid = 1;
+                goto retry;
+            }
                        fidp->refCount++;
-                       break;
+            break;
                }
+    }
+    if (!fidp && (flags & SMB_FLAG_CREATE)) {
+        char eventName[MAX_PATH];
+        EVENT_HANDLE event;
+        sprintf(eventName,"fid_t event vcp=%d fid=%d", vcp->vcID, fid);
+        event = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
+        if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+            afsi_log("Event Object Already Exists: %s", eventName);
+            thrd_CloseHandle(event);
+            fid++;
+            if (fid == 0)
+                fid = 1;
+            goto retry;
         }
-        if (!fidp && (flags & SMB_FLAG_CREATE)) {
+
                fidp = malloc(sizeof(*fidp));
-                memset(fidp, 0, sizeof(*fidp));
+        memset(fidp, 0, sizeof(*fidp));
                osi_QAdd((osi_queue_t **)&vcp->fidsp, &fidp->q);
-                fidp->refCount = 1;
-                fidp->vcp = vcp;
-                lock_InitializeMutex(&fidp->mx, "fid_t mutex");
-                fidp->fid = fid;
+        fidp->refCount = 1;
+        fidp->vcp = vcp;
+        vcp->refCount++;
+        lock_InitializeMutex(&fidp->mx, "fid_t mutex");
+        fidp->fid = fid;
                fidp->curr_chunk = fidp->prev_chunk = -2;
-               fidp->raw_write_event = CreateEvent(NULL, FALSE, TRUE, NULL);
-                if (newFid) {
-                       vcp->fidCounter = fid+1;
-                        if (vcp->fidCounter == 0) vcp->fidCounter = 1;
-                }
+               fidp->raw_write_event = event;
+        if (newFid) {
+            vcp->fidCounter = fid+1;
+            if (vcp->fidCounter == 0) 
+                vcp->fidCounter = 1;
         }
-        lock_ReleaseWrite(&smb_rctLock);
-        return fidp;
+    }
+    lock_ReleaseWrite(&smb_rctLock);
+    return fidp;
 }
 
 void smb_ReleaseFID(smb_fid_t *fidp)
 {
        cm_scache_t *scp;
-        smb_vc_t *vcp;
-        smb_ioctl_t *ioctlp;
+    smb_vc_t *vcp = NULL;
+    smb_ioctl_t *ioctlp;
+
+    if (!fidp)
+        return;
 
        scp = NULL;
        lock_ObtainWrite(&smb_rctLock);
        osi_assert(fidp->refCount-- > 0);
-        if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
+    if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
                vcp = fidp->vcp;
                if (!(fidp->flags & SMB_FID_IOCTL))
                        scp = fidp->scp;
                osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
-               CloseHandle(fidp->raw_write_event);
+               thrd_CloseHandle(fidp->raw_write_event);
 
                /* and see if there is ioctl stuff to free */
-                ioctlp = fidp->ioctlp;
-                if (ioctlp) {
+        ioctlp = fidp->ioctlp;
+        if (ioctlp) {
                        if (ioctlp->prefix) cm_FreeSpace(ioctlp->prefix);
                        if (ioctlp->inAllocp) free(ioctlp->inAllocp);
                        if (ioctlp->outAllocp) free(ioctlp->outAllocp);
                        free(ioctlp);
-                }
-
-                free(fidp);
         }
+
+        free(fidp);
+
+        /* do not call smb_ReleaseVC() because we already have the lock */
+        vcp->refCount--;
+    }
        lock_ReleaseWrite(&smb_rctLock);
 
        /* now release the scache structure */
-        if (scp) cm_ReleaseSCache(scp);
+       if (scp) 
+               cm_ReleaseSCache(scp);
 }
 
 /*
@@ -743,67 +1178,246 @@ char VNLCUserName[] = "%LCUSERNAME%";
 char VNComputerName[] = "%COMPUTERNAME%";
 char VNLCComputerName[] = "%LCCOMPUTERNAME%";
 
+/* List available shares */
+int smb_ListShares()
+{
+       char sbmtpath[256];
+       char pathName[256];
+       char shareBuf[4096];
+       int num_shares=0;
+       char *this_share;
+       int len;
+       char *p;
+       int print_afs = 0;
+       int code;
+
+       /*strcpy(shareNameList[num_shares], "all");
+        strcpy(pathNameList[num_shares++], "/afs");*/
+       fprintf(stderr, "The following shares are available:\n");
+       fprintf(stderr, "Share Name (AFS Path)\n");
+       fprintf(stderr, "---------------------\n");
+       fprintf(stderr, "\\\\%s\\%-16s (%s)\n", smb_localNamep, "ALL", cm_mountRoot);
+
+#ifndef DJGPP
+       code = GetWindowsDirectory(sbmtpath, sizeof(sbmtpath));
+       if (code == 0 || code > sizeof(sbmtpath)) return -1;
+#else
+       strcpy(sbmtpath, cm_confDir);
+#endif /* !DJGPP */
+       strcat(sbmtpath, "/afsdsbmt.ini");
+       len = GetPrivateProfileString("AFS Submounts", NULL, NULL,
+                                                                  shareBuf, sizeof(shareBuf),
+                                                                  sbmtpath);
+       if (len == 0) {
+               return num_shares;
+       }
+
+       this_share = shareBuf;
+       do
+       {
+               print_afs = 0;
+               /*strcpy(shareNameList[num_shares], this_share);*/
+               len = GetPrivateProfileString("AFS Submounts", this_share,
+                                                                          NULL,
+                                                                          pathName, 256,
+                                                                          sbmtpath);
+               if (!len) 
+                       return num_shares;
+               p = pathName;
+               if (strncmp(p, cm_mountRoot, strlen(cm_mountRoot)) != 0)
+            print_afs = 1;
+               while (*p) {
+            if (*p == '\\') *p = '/';    /* change to / */
+            p++;
+               }
+
+               fprintf(stderr, "\\\\%s\\%-16s (%s%s)\n",
+                                smb_localNamep, this_share, (print_afs ? cm_mountRoot : "\0"),
+                                pathName);
+               num_shares++;
+               while (*this_share != 0) this_share++;  /* find next NUL */
+               this_share++;   /* skip past the NUL */
+       } while (*this_share != 0);  /* stop at final NUL */
+
+       return num_shares;
+}
+
 /* find a shareName in the table of submounts */
-int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
+int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
        char **pathNamep)
 {
        DWORD len;
        char pathName[1024];
        char *var;
-       smb_user_t *uidp;
        char temp[1024];
        DWORD sizeTemp;
+    char sbmtpath[MAX_PATH];
+    char *p, *q;
+       HKEY parmKey;
+       DWORD code;
+    DWORD allSubmount = 1;
 
        if (strcmp(shareName, "IPC$") == 0) {
                *pathNamep = NULL;
                return 0;
        }
 
-       if (_stricmp(shareName, "all") == 0) {
+    /* if allSubmounts == 0, only return the //mountRoot/all share 
+     * if in fact it has been been created in the subMounts table.  
+     * This is to allow sites that want to restrict access to the 
+     * world to do so.
+     */
+       code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
+                                               0, KEY_QUERY_VALUE, &parmKey);
+       if (code == ERROR_SUCCESS) {
+        len = sizeof(allSubmount);
+        code = RegQueryValueEx(parmKey, "AllSubmount", NULL, NULL,
+                                (BYTE *) &allSubmount, &len);
+        if (code != ERROR_SUCCESS) {
+            allSubmount = 1;
+        }
+        RegCloseKey (parmKey);
+       }
+
+       if (allSubmount && _stricmp(shareName, "all") == 0) {
                *pathNamep = NULL;
                return 1;
        }
 
+    /* In case, the all share is disabled we need to still be able
+     * to handle ioctl requests 
+     */
+       if (_stricmp(shareName, "ioctl$") == 0) {
+               *pathNamep = strdup("/.__ioctl__");
+               return 1;
+       }
+
+#ifndef DJGPP
+    strcpy(sbmtpath, "afsdsbmt.ini");
+#else /* DJGPP */
+    strcpy(sbmtpath, cm_confDir);
+    strcat(sbmtpath, "/afsdsbmt.ini");
+#endif /* !DJGPP */
        len = GetPrivateProfileString("AFS Submounts", shareName, "",
-                                     pathName, sizeof(pathName), "afsdsbmt.ini");
-       if (len == 0 || len == sizeof(pathName) - 1) {
-               *pathNamep = NULL;
-               return 0;
+                                  pathName, sizeof(pathName), sbmtpath);
+       if (len != 0 && len != sizeof(pathName) - 1) {
+        /* We can accept either unix or PC style AFS pathnames.  Convert
+         * Unix-style to PC style here for internal use. 
+         */
+        p = pathName;
+        if (strncmp(p, cm_mountRoot, strlen(cm_mountRoot)) == 0)
+            p += strlen(cm_mountRoot);  /* skip mount path */
+        q = p;
+        while (*q) {
+            if (*q == '/') *q = '\\';    /* change to \ */
+            q++;
+        }
+
+        while (1)
+        {
+            if (var = smb_stristr(p, VNUserName)) {
+                if (uidp && uidp->unp)
+                    smb_subst(p, var, sizeof(VNUserName),uidp->unp->name);
+                else
+                    smb_subst(p, var, sizeof(VNUserName)," ");
+            }
+            else if (var = smb_stristr(p, VNLCUserName)) 
+            {
+                if (uidp && uidp->unp)
+                    strcpy(temp, uidp->unp->name);
+                else 
+                    strcpy(temp, " ");
+                _strlwr(temp);
+                smb_subst(p, var, sizeof(VNLCUserName), temp);
+            }
+            else if (var = smb_stristr(p, VNComputerName)) 
+            {
+                sizeTemp = sizeof(temp);
+                GetComputerName((LPTSTR)temp, &sizeTemp);
+                smb_subst(p, var, sizeof(VNComputerName), temp);
+            }
+            else if (var = smb_stristr(p, VNLCComputerName)) 
+            {
+                sizeTemp = sizeof(temp);
+                GetComputerName((LPTSTR)temp, &sizeTemp);
+                _strlwr(temp);
+                smb_subst(p, var, sizeof(VNLCComputerName), temp);
+            }
+            else     
+                break;
+        }
+        *pathNamep = strdup(p);
+        return 1;
+    } 
+    else /* create  \\<netbiosName>\<cellname>  */
+    {
+        char * p = shareName; 
+        int rw = 0;
+
+        if ( *p == '.' ) {
+            p++;
+            rw = 1;
+        }
+        /* Get the full name for this cell */
+        code = cm_SearchCellFile(p, temp, 0, 0);
+#ifdef AFS_AFSDB_ENV
+               if (code && cm_dnsEnabled) {
+            int ttl;
+            code = cm_SearchCellByDNS(p, temp, &ttl, 0, 0);
+        }
+#endif
+        /* construct the path */
+        if (code == 0) {     
+            sprintf(pathName,rw ? "/.%s/" : "/%s/",temp);
+            *pathNamep = strdup(strlwr(pathName));
+            return 1;
+        }
        }
+    /* failure */
+    *pathNamep = NULL;
+    return 0;
+}
 
-       while (1)
+/* Client-side offline caching policy types */
+#define CSC_POLICY_MANUAL 0
+#define CSC_POLICY_DOCUMENTS 1
+#define CSC_POLICY_PROGRAMS 2
+#define CSC_POLICY_DISABLE 3
+
+int smb_FindShareCSCPolicy(char *shareName)
+{
+       DWORD len;
+       char policy[1024];
+       char sbmtpath[256];
+
+#ifndef DJGPP
+        strcpy(sbmtpath, "afsdsbmt.ini");
+#else /* DJGPP */
+        strcpy(sbmtpath, cm_confDir);
+        strcat(sbmtpath, "/afsdsbmt.ini");
+#endif /* !DJGPP */
+       len = GetPrivateProfileString("CSC Policy", shareName, "",
+                                     policy, sizeof(policy), sbmtpath);
+       if (len == 0 || len == sizeof(policy) - 1) {
+               return CSC_POLICY_MANUAL;
+       }
+       
+       if (stricmp(policy, "documents") == 0)
        {
-               if (var = smb_stristr(pathName, VNUserName)) {
-                       uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
-                       smb_subst(pathName, var, sizeof(VNUserName),
-                                 uidp->name);
-                       smb_ReleaseUID(uidp);
-               }
-               else if (var = smb_stristr(pathName, VNLCUserName)) {
-                       uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
-                       strcpy(temp, uidp->name);
-                       _strlwr(temp);
-                       smb_subst(pathName, var, sizeof(VNLCUserName), temp);
-                       smb_ReleaseUID(uidp);
-               }
-               else if (var = smb_stristr(pathName, VNComputerName)) {
-                       sizeTemp = sizeof(temp);
-                       GetComputerName((LPTSTR)temp, &sizeTemp);
-                       smb_subst(pathName, var, sizeof(VNComputerName),
-                                 temp);
-               }
-               else if (var = smb_stristr(pathName, VNLCComputerName)) {
-                       sizeTemp = sizeof(temp);
-                       GetComputerName((LPTSTR)temp, &sizeTemp);
-                       _strlwr(temp);
-                       smb_subst(pathName, var, sizeof(VNLCComputerName),
-                                 temp);
-               }
-               else break;
+               return CSC_POLICY_DOCUMENTS;
        }
-
-       *pathNamep = strdup(pathName);
-       return 1;
+       
+       if (stricmp(policy, "programs") == 0)
+       {
+               return CSC_POLICY_PROGRAMS;
+       }
+       
+       if (stricmp(policy, "disable") == 0)
+       {
+               return CSC_POLICY_DISABLE;
+       }
+       
+       return CSC_POLICY_MANUAL;
 }
 
 /* find a dir search structure by cookie value, and return it held.
@@ -813,22 +1427,22 @@ smb_dirSearch_t *smb_FindDirSearchNL(long cookie)
 {
        smb_dirSearch_t *dsp;
         
-        for(dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
+       for(dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
                if (dsp->cookie == cookie) {
                        if (dsp != smb_firstDirSearchp) {
                                /* move to head of LRU queue, too, if we're not already there */
-                               if (smb_lastDirSearchp == (smb_dirSearch_t *) &dsp->q)
-                                       smb_lastDirSearchp = (smb_dirSearch_t *)
-                                               osi_QPrev(&dsp->q);
+                               if (smb_lastDirSearchp == (smb_dirSearch_t *) &dsp->q)
+                                       smb_lastDirSearchp = (smb_dirSearch_t *)
+                                               osi_QPrev(&dsp->q);
                                osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
-                                osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
-                                if (!smb_lastDirSearchp)
-                                       smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
+                               osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
+                               if (!smb_lastDirSearchp)
+                                       smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
                        }
                        dsp->refCount++;
-                        break;
-                }
-        }
+                       break;
+               }
+       }
        return dsp;
 }
 
@@ -837,39 +1451,39 @@ void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
        lock_ObtainWrite(&smb_globalLock);
        dsp->flags |= SMB_DIRSEARCH_DELETE;
        lock_ReleaseWrite(&smb_globalLock);
-       lock_ObtainMutex(&dsp->mx);
+       lock_ObtainMutex(&dsp->mx);
        if(dsp->scp != NULL) {
-             lock_ObtainMutex(&dsp->scp->mx);
-             if (dsp->flags & SMB_DIRSEARCH_BULKST) {
-                   dsp->flags &= ~SMB_DIRSEARCH_BULKST;
+               lock_ObtainMutex(&dsp->scp->mx);
+               if (dsp->flags & SMB_DIRSEARCH_BULKST) {
+                       dsp->flags &= ~SMB_DIRSEARCH_BULKST;
                    dsp->scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
                    dsp->scp->bulkStatProgress = hones;
-             }
-             lock_ReleaseMutex(&dsp->scp->mx);
-       }
-       lock_ReleaseMutex(&dsp->mx);
+               }       
+               lock_ReleaseMutex(&dsp->scp->mx);
+       }       
+       lock_ReleaseMutex(&dsp->mx);
 }
 
 void smb_ReleaseDirSearch(smb_dirSearch_t *dsp)
 {
        cm_scache_t *scp;
         
-        scp = NULL;
+       scp = NULL;
 
        lock_ObtainWrite(&smb_globalLock);
        osi_assert(dsp->refCount-- > 0);
-        if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) {
+       if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) {
                if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
-                       smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
+                       smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
                osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
-                lock_FinalizeMutex(&dsp->mx);
-                scp = dsp->scp;
-                free(dsp);
-        }
+               lock_FinalizeMutex(&dsp->mx);
+               scp = dsp->scp;
+               free(dsp);
+       }
        lock_ReleaseWrite(&smb_globalLock);
-        
+
        /* do this now to avoid spurious locking hierarchy creation */
-        if (scp) cm_ReleaseSCache(scp);
+       if (scp) cm_ReleaseSCache(scp);
 }
 
 /* find a dir search structure by cookie value, and return it held */
@@ -880,7 +1494,7 @@ smb_dirSearch_t *smb_FindDirSearch(long cookie)
        lock_ObtainWrite(&smb_globalLock);
        dsp = smb_FindDirSearchNL(cookie);
        lock_ReleaseWrite(&smb_globalLock);
-        return dsp;
+       return dsp;
 }
 
 /* GC some dir search entries, in the address space expected by the specific protocol.
@@ -891,36 +1505,37 @@ void smb_GCDirSearches(int isV3)
 {
        smb_dirSearch_t *prevp;
        smb_dirSearch_t *tp;
-        smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
-        int victimCount;
-        int i;
+       smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
+       int victimCount;
+       int i;
         
        victimCount = 0;        /* how many have we got so far */
        for(tp = smb_lastDirSearchp; tp; tp=prevp) {
-               prevp = (smb_dirSearch_t *) osi_QPrev(&tp->q);  /* we'll move tp from queue, so
-                                                                * do this early.
-                                                                 */
+               /* we'll move tp from queue, so
+                * do this early.
+                */
+               prevp = (smb_dirSearch_t *) osi_QPrev(&tp->q);  
                /* if no one is using this guy, and we're either in the new protocol,
-                 * or we're in the old one and this is a small enough ID to be useful
-                 * to the old protocol, GC this guy.
-                 */
+                * or we're in the old one and this is a small enough ID to be useful
+                * to the old protocol, GC this guy.
+                */
                if (tp->refCount == 0 && (isV3 || tp->cookie <= 255)) {
                        /* hold and delete */
                        tp->flags |= SMB_DIRSEARCH_DELETE;
-                        victimsp[victimCount++] = tp;
-                        tp->refCount++;
-                }
+                       victimsp[victimCount++] = tp;
+                       tp->refCount++;
+               }
 
                /* don't do more than this */
-                if (victimCount >= SMB_DIRSEARCH_GCMAX) break;
-        }
+               if (victimCount >= SMB_DIRSEARCH_GCMAX) break;
+       }
        
        /* now release them */
-        lock_ReleaseWrite(&smb_globalLock);
-        for(i = 0; i < victimCount; i++) {
+       lock_ReleaseWrite(&smb_globalLock);
+       for(i = 0; i < victimCount; i++) {
                smb_ReleaseDirSearch(victimsp[i]);
-        }
-        lock_ObtainWrite(&smb_globalLock);
+       }
+       lock_ObtainWrite(&smb_globalLock);
 }
 
 /* function for allocating a dir search entry.  We need these to remember enough context
@@ -933,60 +1548,69 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3)
 {
        smb_dirSearch_t *dsp;
        int counter;
-        int maxAllowed;
+       int maxAllowed;
 
        lock_ObtainWrite(&smb_globalLock);
        counter = 0;
 
        /* what's the biggest ID allowed in this version of the protocol */
-        if (isV3) maxAllowed = 65535;
-        else maxAllowed = 255;
+       if (isV3) maxAllowed = 65535;
+       else maxAllowed = 255;
 
        while(1) {
                /* twice so we have enough tries to find guys we GC after one pass;
-                 * 10 extra is just in case I mis-counted.
-                 */
-               if (++counter > 2*maxAllowed+10) osi_panic("afsd: dir search cookie leak",
-                       __FILE__, __LINE__);
-               if (smb_dirSearchCounter > maxAllowed) {
-                       smb_dirSearchCounter = 1;
-                        smb_GCDirSearches(isV3);       /* GC some (drops global lock) */
-               }
+                * 10 extra is just in case I mis-counted.
+                */
+               if (++counter > 2*maxAllowed+10) osi_panic("afsd: dir search cookie leak",
+                                                                                                       __FILE__, __LINE__);
+               if (smb_dirSearchCounter > maxAllowed) {        
+                       smb_dirSearchCounter = 1;
+                       smb_GCDirSearches(isV3);        /* GC some (drops global lock) */
+               }       
                dsp = smb_FindDirSearchNL(smb_dirSearchCounter);
-                if (dsp) {
+               if (dsp) {
                        /* don't need to watch for refcount zero and deleted, since
-                         * we haven't dropped the global lock.
-                         */
+                        * we haven't dropped the global lock.
+                        */
                        dsp->refCount--;
-                        ++smb_dirSearchCounter;
-                        continue;
-               }
+                       ++smb_dirSearchCounter;
+                       continue;
+               }       
                 
-                dsp = malloc(sizeof(*dsp));
-                memset(dsp, 0, sizeof(*dsp));
-                osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
-                if (!smb_lastDirSearchp) smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
-                dsp->cookie = smb_dirSearchCounter;
+               dsp = malloc(sizeof(*dsp));
+               memset(dsp, 0, sizeof(*dsp));
+               osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
+               if (!smb_lastDirSearchp) smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
+               dsp->cookie = smb_dirSearchCounter;
                ++smb_dirSearchCounter;
-                dsp->refCount = 1;
-                lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t");
-                dsp->lastTime = osi_Time();
-                break;
-       }
+               dsp->refCount = 1;
+               lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t");
+               dsp->lastTime = osi_Time();
+               break;
+       }       
        lock_ReleaseWrite(&smb_globalLock);
-        return dsp;
+       return dsp;
 }
 
 static smb_packet_t *GetPacket(void)
 {
        smb_packet_t *tbp;
+#ifdef DJGPP
+        unsigned int npar, seg, tb_sel;
+#endif
+
        lock_ObtainWrite(&smb_globalLock);
        tbp = smb_packetFreeListp;
-        if (tbp) smb_packetFreeListp = tbp->nextp;
+    if (tbp) 
+        smb_packetFreeListp = tbp->nextp;
        lock_ReleaseWrite(&smb_globalLock);
-        if (!tbp) {
-               tbp = GlobalAlloc(GMEM_FIXED, 65540);
-                tbp->magic = SMB_PACKETMAGIC;
+    if (!tbp) {
+#ifndef DJGPP
+        tbp = calloc(65540,1);
+#else /* DJGPP */
+        tbp = malloc(sizeof(smb_packet_t));
+#endif /* !DJGPP */
+        tbp->magic = SMB_PACKETMAGIC;
                tbp->ncbp = NULL;
                tbp->vcp = NULL;
                tbp->resumeCode = 0;
@@ -997,11 +1621,31 @@ static smb_packet_t *GetPacket(void)
                tbp->oddByte = 0;
                tbp->ncb_length = 0;
                tbp->flags = 0;
+        tbp->spacep = NULL;
+        
+#ifdef DJGPP
+        npar = SMB_PACKETSIZE >> 4;  /* number of paragraphs */
+        {
+            signed int retval =
+                __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
+            if (retval == -1) {
+                afsi_log("Cannot allocate %d paragraphs of DOS memory",
+                          npar);
+                osi_panic("",__FILE__,__LINE__);
+            }
+            else {
+                afsi_log("Allocated %d paragraphs of DOS mem at 0x%X",
+                          npar, retval);
+                seg = retval;
+            }
+        }
+        tbp->dos_pkt = (seg * 16) + 0;  /* DOS physical address */
+        tbp->dos_pkt_sel = tb_sel;
+#endif /* DJGPP */
        }
-        
-        osi_assert(tbp->magic == SMB_PACKETMAGIC);
+    osi_assert(tbp->magic == SMB_PACKETMAGIC);
 
-        return tbp;
+    return tbp;
 }
 
 smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
@@ -1009,33 +1653,63 @@ smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
        smb_packet_t *tbp;
        tbp = GetPacket();
        memcpy(tbp, pkt, sizeof(smb_packet_t));
-       tbp->wctp = tbp->data + (pkt->wctp - pkt->data);
+       tbp->wctp = tbp->data + ((unsigned int)pkt->wctp - (unsigned int)pkt->data);
        return tbp;
 }
 
 static NCB *GetNCB(void)
 {
        smb_ncb_t *tbp;
+    NCB *ncbp;
+#ifdef DJGPP
+    unsigned int npar, seg, tb_sel;
+#endif /* DJGPP */
+
        lock_ObtainWrite(&smb_globalLock);
        tbp = smb_ncbFreeListp;
-        if (tbp) smb_ncbFreeListp = tbp->nextp;
+    if (tbp) 
+        smb_ncbFreeListp = tbp->nextp;
        lock_ReleaseWrite(&smb_globalLock);
-        if (!tbp) {
-               tbp = GlobalAlloc(GMEM_FIXED, sizeof(*tbp));
-                tbp->magic = SMB_NCBMAGIC;
+    if (!tbp) {
+#ifndef DJGPP
+        tbp = calloc(sizeof(*tbp),1);
+#else /* DJGPP */
+        tbp = malloc(sizeof(*tbp));
+        npar = (sizeof(NCB)+15) >> 4;  /* number of paragraphs */
+        {
+            signed int retval =
+                __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
+            if (retval == -1) {
+                afsi_log("Cannot allocate %d paragraphs of DOS mem in GetNCB",
+                          npar);
+                osi_panic("",__FILE__,__LINE__);
+            } else {
+                afsi_log("Allocated %d paragraphs of DOS mem at 0x%X in GetNCB",
+                          npar, retval);
+                seg = retval;
+            }
+        }
+        tbp->dos_ncb = (seg * 16) + 0;  /* DOS physical address */
+        tbp->dos_ncb_sel = tb_sel;
+#endif /* !DJGPP */
+        tbp->magic = SMB_NCBMAGIC;
        }
         
-        osi_assert(tbp->magic == SMB_NCBMAGIC);
+    osi_assert(tbp->magic == SMB_NCBMAGIC);
 
        memset(&tbp->ncb, 0, sizeof(NCB));
-        return &tbp->ncb;
+    ncbp = &tbp->ncb;
+#ifdef DJGPP
+    dos_memset(tbp->dos_ncb, 0, sizeof(NCB));
+#endif /* DJGPP */
+    return ncbp;
 }
 
 void smb_FreePacket(smb_packet_t *tbp)
 {
-        osi_assert(tbp->magic == SMB_PACKETMAGIC);
+    osi_assert(tbp->magic == SMB_PACKETMAGIC);
         
-        lock_ObtainWrite(&smb_globalLock);
+    lock_ObtainWrite(&smb_globalLock);
        tbp->nextp = smb_packetFreeListp;
        smb_packetFreeListp = tbp;
        tbp->magic = SMB_PACKETMAGIC;
@@ -1049,39 +1723,39 @@ void smb_FreePacket(smb_packet_t *tbp)
        tbp->oddByte = 0;
        tbp->ncb_length = 0;
        tbp->flags = 0;
-        lock_ReleaseWrite(&smb_globalLock);
+    lock_ReleaseWrite(&smb_globalLock);
 }
 
 static void FreeNCB(NCB *bufferp)
 {
        smb_ncb_t *tbp;
         
-        tbp = (smb_ncb_t *) bufferp;
-        osi_assert(tbp->magic == SMB_NCBMAGIC);
+    tbp = (smb_ncb_t *) bufferp;
+    osi_assert(tbp->magic == SMB_NCBMAGIC);
         
-        lock_ObtainWrite(&smb_globalLock);
+    lock_ObtainWrite(&smb_globalLock);
        tbp->nextp = smb_ncbFreeListp;
        smb_ncbFreeListp = tbp;
-        lock_ReleaseWrite(&smb_globalLock);
+    lock_ReleaseWrite(&smb_globalLock);
 }
 
 /* get a ptr to the data part of a packet, and its count */
 unsigned char *smb_GetSMBData(smb_packet_t *smbp, int *nbytesp)
 {
-        int parmBytes;
-        int dataBytes;
-        unsigned char *afterParmsp;
+    int parmBytes;
+    int dataBytes;
+    unsigned char *afterParmsp;
 
-        parmBytes = *smbp->wctp << 1;
+    parmBytes = *smbp->wctp << 1;
        afterParmsp = smbp->wctp + parmBytes + 1;
         
-        dataBytes = afterParmsp[0] + (afterParmsp[1]<<8);
-        if (nbytesp) *nbytesp = dataBytes;
+    dataBytes = afterParmsp[0] + (afterParmsp[1]<<8);
+    if (nbytesp) *nbytesp = dataBytes;
         
        /* don't forget to skip the data byte count, since it follows
-         * the parameters; that's where the "2" comes from below.
-         */
-        return (unsigned char *) (afterParmsp + 2);
+     * the parameters; that's where the "2" comes from below.
+     */
+    return (unsigned char *) (afterParmsp + 2);
 }
 
 /* must set all the returned parameters before playing around with the
@@ -1090,33 +1764,41 @@ unsigned char *smb_GetSMBData(smb_packet_t *smbp, int *nbytesp)
  */
 void smb_SetSMBDataLength(smb_packet_t *smbp, unsigned int dsize)
 {
-        unsigned char *afterParmsp;
+       unsigned char *afterParmsp;
 
        afterParmsp = smbp->wctp + ((*smbp->wctp)<<1) + 1;
         
        *afterParmsp++ = dsize & 0xff;
-        *afterParmsp = (dsize>>8) & 0xff;
+       *afterParmsp = (dsize>>8) & 0xff;
 }
 
 /* return the parm'th parameter in the smbp packet */
 unsigned int smb_GetSMBParm(smb_packet_t *smbp, int parm)
 {
-        int parmCount;
+       int parmCount;
        unsigned char *parmDatap;
 
        parmCount = *smbp->wctp;
 
        if (parm >= parmCount) {
-               HANDLE h;
+#ifndef DJGPP
+        HANDLE h;
                char *ptbuf[1];
                char s[100];
                h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
                sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
-                       parm, parmCount, smbp->ncb_length);
+                               parm, parmCount, smbp->ncb_length);
                ptbuf[0] = s;
                ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1006, NULL,
-                           1, smbp->ncb_length, ptbuf, smbp);
+                                       1, smbp->ncb_length, ptbuf, smbp);
                DeregisterEventSource(h);
+#else /* DJGPP */
+               char s[100];
+
+               sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
+                               parm, parmCount, smbp->ncb_length);
+               osi_Log0(smb_logp, s);
+#endif /* !DJGPP */
                osi_panic(s, __FILE__, __LINE__);
        }
        parmDatap = smbp->wctp + (2*parm) + 1;
@@ -1127,27 +1809,37 @@ unsigned int smb_GetSMBParm(smb_packet_t *smbp, int parm)
 /* return the parm'th parameter in the smbp packet */
 unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
 {
-        int parmCount;
+       int parmCount;
        unsigned char *parmDatap;
 
        parmCount = *smbp->wctp;
 
        if (parm * 2 + offset >= parmCount * 2) {
+#ifndef DJGPP
                HANDLE h;
                char *ptbuf[1];
                char s[100];
                h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
                sprintf(s, "Bad SMB param %d offset %d out of %d, ncb len %d",
-                       parm, offset, parmCount, smbp->ncb_length);
+                               parm, offset, parmCount, smbp->ncb_length);
                ptbuf[0] = s;
                ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1006, NULL,
-                           1, smbp->ncb_length, ptbuf, smbp);
+                                       1, smbp->ncb_length, ptbuf, smbp);
                DeregisterEventSource(h);
-               osi_panic(s, __FILE__, __LINE__);
-       }
+#else /* DJGPP */
+               char s[100];
+                
+               sprintf(s, "Bad SMB param %d offset %d out of %d, "
+                               "ncb len %d",
+                                parm, offset, parmCount, smbp->ncb_length);
+               osi_Log0(smb_logp, s);
+#endif /* !DJGPP */
+
+               osi_panic(s, __FILE__, __LINE__);
+       }
        parmDatap = smbp->wctp + (2*parm) + 1 + offset;
        
-        return parmDatap[0] + (parmDatap[1] << 8);
+       return parmDatap[0] + (parmDatap[1] << 8);
 }
 
 void smb_SetSMBParm(smb_packet_t *smbp, int slot, unsigned int parmValue)
@@ -1157,9 +1849,9 @@ void smb_SetSMBParm(smb_packet_t *smbp, int slot, unsigned int parmValue)
        /* make sure we have enough slots */
        if (*smbp->wctp <= slot) *smbp->wctp = slot+1;
         
-        parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
-        *parmDatap++ = parmValue & 0xff;
-        *parmDatap = (parmValue>>8) & 0xff;
+       parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
+       *parmDatap++ = parmValue & 0xff;
+       *parmDatap = (parmValue>>8) & 0xff;
 }
 
 void smb_SetSMBParmLong(smb_packet_t *smbp, int slot, unsigned int parmValue)
@@ -1210,80 +1902,84 @@ void smb_StripLastComponent(char *outPathp, char **lastComponentp, char *inPathp
 {
        char *lastSlashp;
         
-        lastSlashp = strrchr(inPathp, '\\');
+       lastSlashp = strrchr(inPathp, '\\');
        if (lastComponentp)
                *lastComponentp = lastSlashp;
-        if (lastSlashp) {
+       if (lastSlashp) {
                while (1) {
-                       if (inPathp == lastSlashp) break;
+                       if (inPathp == lastSlashp) 
+                               break;
                        *outPathp++ = *inPathp++;
-                }
-                *outPathp++ = 0;
-        }
+               }
+               *outPathp++ = 0;
+       }
        else {
                *outPathp++ = 0;
-        }
+       }
 }
 
 unsigned char *smb_ParseASCIIBlock(unsigned char *inp, char **chainpp)
 {
-       if (*inp++ != 0x4) return NULL;
-        if (chainpp) {
+       if (*inp++ != 0x4) 
+               return NULL;
+       if (chainpp) {
                *chainpp = inp + strlen(inp) + 1;       /* skip over null-terminated string */
-        }
-        return inp;
+       }
+       return inp;
 }
 
 unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *lengthp)
 {
        int tlen;
 
-       if (*inp++ != 0x5) return NULL;
-        tlen = inp[0] + (inp[1]<<8);
-        inp += 2;              /* skip length field */
+       if (*inp++ != 0x5) 
+               return NULL;
+       tlen = inp[0] + (inp[1]<<8);
+       inp += 2;               /* skip length field */
         
-        if (chainpp) {
+       if (chainpp) {
                *chainpp = inp + tlen;
-        }
+       }
         
-        if (lengthp) *lengthp = tlen;
+       if (lengthp) 
+               *lengthp = tlen;
         
-        return inp;
-}
+       return inp;
+}      
 
 /* format a packet as a response */
 void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op)
 {
        smb_t *outp;
-        smb_t *inSmbp;
+       smb_t *inSmbp;
 
-        outp = (smb_t *) op;
+       outp = (smb_t *) op;
        
-        /* zero the basic structure through the smb_wct field, and zero the data
-         * size field, assuming that wct stays zero; otherwise, you have to 
-         * explicitly set the data size field, too.
-         */
+       /* zero the basic structure through the smb_wct field, and zero the data
+        * size field, assuming that wct stays zero; otherwise, you have to 
+        * explicitly set the data size field, too.
+        */
        inSmbp = (smb_t *) inp;
        memset(outp, 0, sizeof(smb_t)+2);
-        outp->id[0] = 0xff;
-        outp->id[1] = 'S';
-        outp->id[2] = 'M';
-        outp->id[3] = 'B';
+       outp->id[0] = 0xff;
+       outp->id[1] = 'S';
+       outp->id[2] = 'M';
+       outp->id[3] = 'B';
        if (inp) {
                outp->com = inSmbp->com;
-               outp->tid = inSmbp->tid;
-               outp->pid = inSmbp->pid;
-               outp->uid = inSmbp->uid;
-               outp->mid = inSmbp->mid;
+               outp->tid = inSmbp->tid;
+               outp->pid = inSmbp->pid;
+               outp->uid = inSmbp->uid;
+               outp->mid = inSmbp->mid;
                outp->res[0] = inSmbp->res[0];
                outp->res[1] = inSmbp->res[1];
-               op->inCom = inSmbp->com;
+               op->inCom = inSmbp->com;
        }
-        outp->reb = 0x80;      /* SERVER_RESP */
+       outp->reb = 0x80;       /* SERVER_RESP */
        outp->flg2 = 0x1;       /* KNOWS_LONG_NAMES */
 
        /* copy fields in generic packet area */
-        op->wctp = &outp->wct;
+       op->wctp = &outp->wct;
 }
 
 /* send a (probably response) packet; vcp tells us to whom to send it.
@@ -1292,33 +1988,49 @@ void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op
 void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
 {
        NCB *ncbp;
-        int extra;
-        long code;
-        unsigned char *tp;
+       int extra;
+       long code = 0;
+       unsigned char *tp;
        int localNCB = 0;
+#ifdef DJGPP
+       dos_ptr dos_ncb;
+#endif /* DJGPP */
         
-        ncbp = inp->ncbp;
+       ncbp = inp->ncbp;
        if (ncbp == NULL) {
                ncbp = GetNCB();
                localNCB = 1;
        }
+#ifdef DJGPP
+       dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
        memset((char *)ncbp, 0, sizeof(NCB));
 
-        extra = 2 * (*inp->wctp);      /* space used by parms, in bytes */
+       extra = 2 * (*inp->wctp);       /* space used by parms, in bytes */
        tp = inp->wctp + 1+ extra;      /* points to count of data bytes */
-        extra += tp[0] + (tp[1]<<8);
-        extra += (inp->wctp - inp->data);      /* distance to last wct field */
-        extra += 3;                    /* wct and length fields */
-        
-        ncbp->ncb_length = extra;      /* bytes to send */
-        ncbp->ncb_lsn = (unsigned char) vcp->lsn;      /* vc to use */
-       ncbp->ncb_lana_num = smb_LANadapter;
-        ncbp->ncb_command = NCBSEND;   /* op means send data */
-        ncbp->ncb_buffer = (char *) inp;/* packet */
+       extra += tp[0] + (tp[1]<<8);
+       extra += ((unsigned int)inp->wctp - (unsigned int)inp->data);   /* distance to last wct field */
+       extra += 3;                     /* wct and length fields */
+        
+       ncbp->ncb_length = extra;       /* bytes to send */
+       ncbp->ncb_lsn = (unsigned char) vcp->lsn;       /* vc to use */
+       ncbp->ncb_lana_num = vcp->lana;
+       ncbp->ncb_command = NCBSEND;    /* op means send data */
+#ifndef DJGPP
+       ncbp->ncb_buffer = (char *) inp;/* packet */
+       code = Netbios(ncbp);
+#else /* DJGPP */
+       ncbp->ncb_buffer = inp->dos_pkt;/* packet */
+       ((smb_ncb_t*)ncbp)->orig_pkt = inp;
+
+       /* copy header information from virtual to DOS address space */
+       dosmemput((char*)inp, SMB_PACKETSIZE, inp->dos_pkt);
+       code = Netbios(ncbp, dos_ncb);
+#endif /* !DJGPP */
         
-        code = Netbios(ncbp);
        if (code != 0)
-               osi_Log1(afsd_logp, "SendPacket failure code %d", code);
+               osi_Log1(smb_logp, "SendPacket failure code %d", code);
 
        if (localNCB)
                FreeNCB(ncbp);
@@ -1329,65 +2041,70 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
        unsigned long NTStatus;
 
        /* map CM_ERROR_* errors to NT 32-bit status codes */
-        if (code == CM_ERROR_NOSUCHCELL) {
+    /* NT Status codes are listed in ntstatus.h not winerror.h */
+       if (code == CM_ERROR_NOSUCHCELL) {
                NTStatus = 0xC000000FL; /* No such file */
-        }
-        else if (code == CM_ERROR_NOSUCHVOLUME) {
+       }
+       else if (code == CM_ERROR_NOSUCHVOLUME) {
                NTStatus = 0xC000000FL; /* No such file */
-        }
-        else if (code == CM_ERROR_TIMEDOUT) {
-               NTStatus = 0xC00000CFL; /* Paused */
-        }
-        else if (code == CM_ERROR_RETRY) {
+       }
+       else if (code == CM_ERROR_TIMEDOUT) {
+               NTStatus = 0xC00000CFL; /* Sharing Paused */
+       }
+       else if (code == CM_ERROR_RETRY) {
                NTStatus = 0xC000022DL; /* Retry */
-        }
-        else if (code == CM_ERROR_NOACCESS) {
+       }
+       else if (code == CM_ERROR_NOACCESS) {
                NTStatus = 0xC0000022L; /* Access denied */
-        }
+       }
        else if (code == CM_ERROR_READONLY) {
                NTStatus = 0xC00000A2L; /* Write protected */
-       }
-        else if (code == CM_ERROR_NOSUCHFILE) {
+       }       
+       else if (code == CM_ERROR_NOSUCHFILE) {
                NTStatus = 0xC000000FL; /* No such file */
-        }
+       }
        else if (code == CM_ERROR_NOSUCHPATH) {
                NTStatus = 0xC000003AL; /* Object path not found */
-       }
-        else if (code == CM_ERROR_TOOBIG) {
+       }               
+       else if (code == CM_ERROR_TOOBIG) {
                NTStatus = 0xC000007BL; /* Invalid image format */
-        }
-        else if (code == CM_ERROR_INVAL) {
+       }
+       else if (code == CM_ERROR_INVAL) {
                NTStatus = 0xC000000DL; /* Invalid parameter */
-        }
-        else if (code == CM_ERROR_BADFD) {
+       }
+       else if (code == CM_ERROR_BADFD) {
                NTStatus = 0xC0000008L; /* Invalid handle */
-        }
-        else if (code == CM_ERROR_BADFDOP) {
+       }
+       else if (code == CM_ERROR_BADFDOP) {
                NTStatus = 0xC0000022L; /* Access denied */
-        }
-        else if (code == CM_ERROR_EXISTS) {
+       }
+       else if (code == CM_ERROR_EXISTS) {
                NTStatus = 0xC0000035L; /* Object name collision */
-        }
+       }
        else if (code == CM_ERROR_NOTEMPTY) {
                NTStatus = 0xC0000101L; /* Directory not empty */
-       }
-        else if (code == CM_ERROR_CROSSDEVLINK) {
+       }       
+       else if (code == CM_ERROR_CROSSDEVLINK) {
                NTStatus = 0xC00000D4L; /* Not same device */
-        }
+       }
        else if (code == CM_ERROR_NOTDIR) {
                NTStatus = 0xC0000103L; /* Not a directory */
-        }
-        else if (code == CM_ERROR_ISDIR) {
+       }
+       else if (code == CM_ERROR_ISDIR) {
                NTStatus = 0xC00000BAL; /* File is a directory */
-        }
-        else if (code == CM_ERROR_BADOP) {
+       }
+       else if (code == CM_ERROR_BADOP) {
                NTStatus = 0xC09820FFL; /* SMB no support */
-        }
+       }
        else if (code == CM_ERROR_BADSHARENAME) {
                NTStatus = 0xC00000CCL; /* Bad network name */
        }
        else if (code == CM_ERROR_NOIPC) {
-               NTStatus = 0xC00000CCL; /* Bad network name */
+#ifdef COMMENT
+               NTStatus = 0xC0000022L; /* Access Denied */
+#else
+        NTStatus = 0xC000013DL; /* Remote Resources */
+#endif
        }
        else if (code == CM_ERROR_CLOCKSKEW) {
                NTStatus = 0xC0000133L; /* Time difference at DC */
@@ -1419,100 +2136,112 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
        else if (code == CM_ERROR_BUFFERTOOSMALL) {
                NTStatus = 0xC0000023L; /* Buffer too small */
        }
-        else {
+    else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
+               NTStatus = 0xC0000035L; /* Object name collision */
+    }
+       else if (code == CM_ERROR_BADPASSWORD) {
+               NTStatus = 0xC000006DL; /* unknown username or bad password */
+       }
+       else if (code == CM_ERROR_BADLOGONTYPE) {
+               NTStatus = 0xC000015BL; /* logon type not granted */
+       }
+       else if (code == CM_ERROR_GSSCONTINUE) {
+               NTStatus = 0xC0000016L; /* more processing required */
+       }
+       else {
                NTStatus = 0xC0982001L; /* SMB non-specific error */
-        }
+       }
 
-        *NTStatusp = NTStatus;
-       osi_Log2(afsd_logp, "SMB SEND code %x as NT %x", code, NTStatus);
+       *NTStatusp = NTStatus;
+       osi_Log2(smb_logp, "SMB SEND code %x as NT %x", code, NTStatus);
 }
 
 void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
        unsigned char *classp)
 {
        unsigned char class;
-        unsigned short error;
+       unsigned short error;
 
        /* map CM_ERROR_* errors to SMB errors */
-        if (code == CM_ERROR_NOSUCHCELL) {
+       if (code == CM_ERROR_NOSUCHCELL) {
                class = 1;
-                error = 3;     /* bad path */
-        }
-        else if (code == CM_ERROR_NOSUCHVOLUME) {
+               error = 3;      /* bad path */
+       }
+       else if (code == CM_ERROR_NOSUCHVOLUME) {
                class = 1;
-                error = 3;     /* bad path */
-        }
-        else if (code == CM_ERROR_TIMEDOUT) {
+               error = 3;      /* bad path */
+       }
+       else if (code == CM_ERROR_TIMEDOUT) {
                class = 2;
-                error = 81;    /* server is paused */
-        }
-        else if (code == CM_ERROR_RETRY) {
+               error = 81;     /* server is paused */
+       }
+       else if (code == CM_ERROR_RETRY) {
                class = 2;      /* shouldn't happen */
-                error = 1;
-        }
-        else if (code == CM_ERROR_NOACCESS) {
+               error = 1;
+       }
+       else if (code == CM_ERROR_NOACCESS) {
                class = 2;
-                error = 4;     /* bad access */
-        }
+               error = 4;      /* bad access */
+       }
        else if (code == CM_ERROR_READONLY) {
                class = 3;
                error = 19;     /* read only */
        }
-        else if (code == CM_ERROR_NOSUCHFILE) {
+       else if (code == CM_ERROR_NOSUCHFILE) {
                class = 1;
-                error = 2;     /* ENOENT! */
-        }
+               error = 2;      /* ENOENT! */
+       }
        else if (code == CM_ERROR_NOSUCHPATH) {
                class = 1;
                error = 3;      /* Bad path */
        }
-        else if (code == CM_ERROR_TOOBIG) {
+       else if (code == CM_ERROR_TOOBIG) {
                class = 1;
                error = 11;     /* bad format */
-        }
-        else if (code == CM_ERROR_INVAL) {
+       }
+       else if (code == CM_ERROR_INVAL) {
                class = 2;      /* server non-specific error code */
-                error = 1;
-        }
-        else if (code == CM_ERROR_BADFD) {
+               error = 1;
+       }
+       else if (code == CM_ERROR_BADFD) {
                class = 1;
-                error = 6;     /* invalid file handle */
-        }
-        else if (code == CM_ERROR_BADFDOP) {
+               error = 6;      /* invalid file handle */
+       }
+       else if (code == CM_ERROR_BADFDOP) {
                class = 1;      /* invalid op on FD */
-                error = 5;
-        }
-        else if (code == CM_ERROR_EXISTS) {
+               error = 5;
+       }
+       else if (code == CM_ERROR_EXISTS) {
                class = 1;
-                error = 80;    /* file already exists */
-        }
+               error = 80;     /* file already exists */
+       }
        else if (code == CM_ERROR_NOTEMPTY) {
                class = 1;
                error = 5;      /* delete directory not empty */
        }
-        else if (code == CM_ERROR_CROSSDEVLINK) {
+       else if (code == CM_ERROR_CROSSDEVLINK) {
                class = 1;
-                error = 17;    /* EXDEV */
-        }
+               error = 17;     /* EXDEV */
+       }
        else if (code == CM_ERROR_NOTDIR) {
                class = 1;      /* bad path */
-                error = 3;
-        }
-        else if (code == CM_ERROR_ISDIR) {
+               error = 3;
+       }
+       else if (code == CM_ERROR_ISDIR) {
                class = 1;      /* access denied; DOS doesn't have a good match */
-                error = 5;
-        }
-        else if (code == CM_ERROR_BADOP) {
+               error = 5;
+       }
+       else if (code == CM_ERROR_BADOP) {
                class = 2;
-                error = 65535;
-        }
+               error = 65535;
+       }
        else if (code == CM_ERROR_BADSHARENAME) {
                class = 2;
                error = 6;
        }
        else if (code == CM_ERROR_NOIPC) {
-               class = 1;
-               error = 66;
+               class = 2;
+               error = 4; /* bad access */
        }
        else if (code == CM_ERROR_CLOCKSKEW) {
                class = 1;      /* invalid function */
@@ -1566,14 +2295,23 @@ void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
                class = 1;
                error = 18;     /* no files in search */
        }
-        else {
+       else if (code == CM_ERROR_RENAME_IDENTICAL) {
+               class = 1;
+               error = 183;     /* Samba uses this */
+       }
+       else if (code == CM_ERROR_BADPASSWORD || code == CM_ERROR_BADLOGONTYPE) {
+               /* we don't have a good way of reporting CM_ERROR_BADLOGONTYPE */
                class = 2;
-                error = 1;
-        }
+               error = 2; /* bad password */
+       }
+       else {
+               class = 2;
+               error = 1;
+       }
 
        *scodep = error;
-        *classp = class;
-        osi_Log3(afsd_logp, "SMB SEND code %x as SMB %d: %d", code, class, error);
+       *classp = class;
+       osi_Log3(smb_logp, "SMB SEND code %x as SMB %d: %d", code, class, error);
 }
 
 long smb_SendCoreBadOp(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
@@ -1607,10 +2345,16 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
        long count, minCount, finalCount;
        unsigned short fd;
        smb_fid_t *fidp;
-       long code;
+       long code = 0;
        cm_user_t *userp = NULL;
-       char *rawBuf;
-       NCB *ncbp;
+    NCB *ncbp;
+    int rc;
+#ifndef DJGPP
+    char *rawBuf = NULL;
+#else
+    dos_ptr rawBuf = NULL;
+    dos_ptr dos_ncb;
+#endif /* DJGPP */
 
        rawBuf = NULL;
        finalCount = 0;
@@ -1621,54 +2365,100 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
        offset.HighPart = 0;    /* too bad */
        offset.LowPart = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
 
-       osi_Log3(afsd_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x, size 0x%x",
-                fd, offset.LowPart, count);
+       osi_Log3(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x, size 0x%x",
+             fd, offset.LowPart, count);
 
        fidp = smb_FindFID(vcp, fd, 0);
        if (!fidp)
                goto send1;
 
-       if (fidp->flags & SMB_FID_IOCTL)
-               return smb_IoctlReadRaw(fidp, vcp, inp, outp);
-
-       userp = smb_GetUser(vcp, inp);
-
        lock_ObtainMutex(&smb_RawBufLock);
        if (smb_RawBufs) {
                /* Get a raw buf, from head of list */
                rawBuf = smb_RawBufs;
+#ifndef DJGPP
                smb_RawBufs = *(char **)smb_RawBufs;
+#else /* DJGPP */
+        smb_RawBufs = _farpeekl(_dos_ds, smb_RawBufs);
+#endif /* !DJGPP */
        }
        lock_ReleaseMutex(&smb_RawBufLock);
        if (!rawBuf)
-               goto send;
+               goto send1a;
+
+    if (fidp->flags & SMB_FID_IOCTL)
+    {
+#ifndef DJGPP
+        rc = smb_IoctlReadRaw(fidp, vcp, inp, outp);
+#else
+        rc = smb_IoctlReadRaw(fidp, vcp, inp, outp, rawBuf);
+#endif
+        if (rawBuf) {
+            /* Give back raw buffer */
+            lock_ObtainMutex(&smb_RawBufLock);
+#ifndef DJGPP
+            *((char **) rawBuf) = smb_RawBufs;
+#else /* DJGPP */
+            _farpokel(_dos_ds, rawBuf, smb_RawBufs);
+#endif /* !DJGPP */
+            
+            smb_RawBufs = rawBuf;
+            lock_ReleaseMutex(&smb_RawBufLock);
+        }
+
+        smb_ReleaseFID(fidp);
+        return rc;
+    }
+        
+    userp = smb_GetUser(vcp, inp);
 
+#ifndef DJGPP
        code = smb_ReadData(fidp, &offset, count, rawBuf, userp, &finalCount);
+#else /* DJGPP */
+    /* have to give ReadData flag so it will treat buffer as DOS mem. */
+    code = smb_ReadData(fidp, &offset, count, (unsigned char *)rawBuf,
+                        userp, &finalCount, TRUE /* rawFlag */);
+#endif /* !DJGPP */
+
        if (code != 0)
                goto send;
 
-send:
+  send:
+    cm_ReleaseUser(userp);
+
+  send1a:
        smb_ReleaseFID(fidp);
 
-       cm_ReleaseUser(userp);
-send1:
+  send1:
        ncbp = outp->ncbp;
+#ifdef DJGPP
+    dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
        memset((char *)ncbp, 0, sizeof(NCB));
 
        ncbp->ncb_length = (unsigned short) finalCount;
        ncbp->ncb_lsn = (unsigned char) vcp->lsn;
-       ncbp->ncb_lana_num = smb_LANadapter;
+       ncbp->ncb_lana_num = vcp->lana;
        ncbp->ncb_command = NCBSEND;
        ncbp->ncb_buffer = rawBuf;
 
+#ifndef DJGPP
        code = Netbios(ncbp);
+#else /* DJGPP */
+       code = Netbios(ncbp, dos_ncb);
+#endif /* !DJGPP */
        if (code != 0)
-               osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
+               osi_Log1(smb_logp, "ReadRaw send failure code %d", code);
 
        if (rawBuf) {
                /* Give back raw buffer */
                lock_ObtainMutex(&smb_RawBufLock);
+#ifndef DJGPP
                *((char **) rawBuf) = smb_RawBufs;
+#else /* DJGPP */
+        _farpokel(_dos_ds, rawBuf, smb_RawBufs);
+#endif /* !DJGPP */
+
                smb_RawBufs = rawBuf;
                lock_ReleaseMutex(&smb_RawBufLock);
        }
@@ -1689,26 +2479,36 @@ long smb_ReceiveCoreUnlockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
 long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *namep;
-        int coreProtoIndex;
-        int v3ProtoIndex;
+    char *datap;
+       int coreProtoIndex;
+       int v3ProtoIndex;
        int NTProtoIndex;
-        int protoIndex;                        /* index we're using */
-        int namex;
-        long dbytes;
+       int protoIndex;                         /* index we're using */
+       int namex;
+       int dbytes;
        int entryLength;
-        int tcounter;
-       char protocol_array[10][1024]; /* protocol signature of the client */
+       int tcounter;
+       char protocol_array[10][1024];  /* protocol signature of the client */
+    int caps;                       /* capabilities */
+    time_t unixTime;
+       long dosTime;
+       TIME_ZONE_INFORMATION tzi;
 
-        
-       osi_Log1(afsd_logp, "SMB receive negotiate; %d + 1 ongoing ops",
-                ongoingOps - 1);
+    osi_Log1(smb_logp, "SMB receive negotiate; %d + 1 ongoing ops",
+                        ongoingOps - 1);
        if (!isGateway) {
                if (active_vcp) {
                        DWORD now = GetCurrentTime();
                        if (now - last_msg_time >= 30000
-                             && now - last_msg_time <= 90000) {
-                               osi_Log1(afsd_logp,
-                                        "Setting dead_vcp %x", active_vcp);
+                               && now - last_msg_time <= 90000) {
+                               osi_Log1(smb_logp,
+                                                "Setting dead_vcp %x", active_vcp);
+                if (dead_vcp) {
+                    smb_ReleaseVC(dead_vcp);
+                    osi_Log1(smb_logp,
+                              "Previous dead_vcp %x", dead_vcp);
+                }
+                smb_HoldVC(active_vcp);
                                dead_vcp = active_vcp;
                                dead_vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
                        }
@@ -1717,99 +2517,113 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK;
 
-        namep = smb_GetSMBData(inp, &dbytes);
-        namex = 0;
+       namep = smb_GetSMBData(inp, &dbytes);
+       namex = 0;
        tcounter = 0;
        coreProtoIndex = -1;            /* not found */
-        v3ProtoIndex = -1;
+       v3ProtoIndex = -1;
        NTProtoIndex = -1;
-        while(namex < dbytes) {
-               osi_Log1(afsd_logp, "Protocol %s",
-                        osi_LogSaveString(afsd_logp, namep+1));
+       while(namex < dbytes) {
+               osi_Log1(smb_logp, "Protocol %s",
+                                osi_LogSaveString(smb_logp, namep+1));
                strcpy(protocol_array[tcounter], namep+1);
 
                /* namep points at the first protocol, or really, a 0x02
-                 * byte preceding the null-terminated ASCII name.
-                 */
-               if (strcmp("PC NETWORK PROGRAM 1.0", namep+1) == 0) {
-                       coreProtoIndex = tcounter;
-               }
-                else if (smb_useV3 && strcmp("LM1.2X002", namep+1) == 0) {
+                * byte preceding the null-terminated ASCII name.
+                */
+               if (strcmp("PC NETWORK PROGRAM 1.0", namep+1) == 0) {
+                       coreProtoIndex = tcounter;
+               }       
+               else if (smb_useV3 && strcmp("LM1.2X002", namep+1) == 0) {
                        v3ProtoIndex = tcounter;
-                }
+               }
                else if (smb_useV3 && strcmp("NT LM 0.12", namep+1) == 0) {
                        NTProtoIndex = tcounter;
                }
 
                /* compute size of protocol entry */
                entryLength = strlen(namep+1);
-                entryLength += 2;      /* 0x02 bytes and null termination */
+        entryLength += 2;      /* 0x02 bytes and null termination */
                 
-                /* advance over this protocol entry */
+        /* advance over this protocol entry */
                namex += entryLength;
-                namep += entryLength;
-                tcounter++;            /* which proto entry we're looking at */
-        }
+        namep += entryLength;
+        tcounter++;            /* which proto entry we're looking at */
+       }
+#ifndef NOMOREFILESFIX
        /* 
         * NOTE: We can determine what OS (NT4.0, W2K, W9X, etc)
         * the client is running by reading the protocol signature.
         * ie. the order in which it sends us the protocol list.
         *
         * Special handling for Windows 2000 clients (defect 11765 )
+     * <asanka:11Jun03> Proto signature is the same for Win XP. </>
         */
        if (tcounter == 6) {
-              int i = 0;
-              smb_t *ip = (smb_t *) inp;
-              smb_t *op = (smb_t *) outp;
-
-              if ((strcmp("PC NETWORK PROGRAM 1.0", protocol_array[0]) == 0) &&
-                  (strcmp("LANMAN1.0", protocol_array[1]) == 0) &&
-                  (strcmp("Windows for Workgroups 3.1a", protocol_array[2]) == 0) &&
-                  (strcmp("LM1.2X002", protocol_array[3]) == 0) &&
-                  (strcmp("LANMAN2.1", protocol_array[4]) == 0) &&
-                  (strcmp("NT LM 0.12", protocol_array[5]) == 0)) {
-                     isWindows2000 = TRUE;
-                     osi_Log0(afsd_logp, "Looks like a Windows 2000 client");
-                     /* 
-                      * HACK: for now - just negotiate a lower protocol till we 
-                      * figure out which flag/flag2 or some other field 
-                      * (capabilities maybe?) to set in order for this to work
-                      * correctly with Windows 2000 clients (defect 11765)
-                      */
-                     NTProtoIndex = -1;
-                     /* Things to try (after looking at tcpdump output could be
-                      * setting flags and flags2 to 0x98 and 0xc853 like this
-                      * op->reb = 0x98; op->flg2 = 0xc853;
-                      * osi_Log2(afsd_logp, "Flags:0x%x Flags2:0x%x", ip->reb, ip->flg2);
-                      */
-              }
-       }
-
-        if (NTProtoIndex != -1) {
+               int i = 0;
+               smb_t *ip = (smb_t *) inp;
+               smb_t *op = (smb_t *) outp;
+
+               if ((strcmp("PC NETWORK PROGRAM 1.0", protocol_array[0]) == 0) &&
+                        (strcmp("LANMAN1.0", protocol_array[1]) == 0) &&
+                        (strcmp("Windows for Workgroups 3.1a", protocol_array[2]) == 0) &&
+                        (strcmp("LM1.2X002", protocol_array[3]) == 0) &&
+                        (strcmp("LANMAN2.1", protocol_array[4]) == 0) &&
+                        (strcmp("NT LM 0.12", protocol_array[5]) == 0)) {
+                       isWindows2000 = TRUE;
+                       osi_Log0(smb_logp, "Looks like a Windows 2000 client");
+                       /* 
+                        * HACK: for now - just negotiate a lower protocol till we 
+                        * figure out which flag/flag2 or some other field 
+                        * (capabilities maybe?) to set in order for this to work
+                        * correctly with Windows 2000 clients (defect 11765)
+                        */
+                       NTProtoIndex = -1;
+                       /* Things to try (after looking at tcpdump output could be
+                        * setting flags and flags2 to 0x98 and 0xc853 like this
+                        * op->reb = 0x98; op->flg2 = 0xc853;
+                        * osi_Log2(smb_logp, "Flags:0x%x Flags2:0x%x", ip->reb, ip->flg2);
+                        */
+               }       
+       }       
+#endif /* NOMOREFILESFIX */
+
+       if (NTProtoIndex != -1) {
                protoIndex = NTProtoIndex;
                vcp->flags |= (SMB_VCFLAG_USENT | SMB_VCFLAG_USEV3);
        }
        else if (v3ProtoIndex != -1) {
-               protoIndex = v3ProtoIndex;
-                vcp->flags |= SMB_VCFLAG_USEV3;
-       }
-        else if (coreProtoIndex != -1) {
-               protoIndex = coreProtoIndex;
-                vcp->flags |= SMB_VCFLAG_USECORE;
-       }
+               protoIndex = v3ProtoIndex;
+               vcp->flags |= SMB_VCFLAG_USEV3;
+       }       
+       else if (coreProtoIndex != -1) {
+               protoIndex = coreProtoIndex;
+               vcp->flags |= SMB_VCFLAG_USECORE;
+       }       
        else protoIndex = -1;
 
-        if (protoIndex == -1)
-               return CM_ERROR_INVAL;
+       if (protoIndex == -1)
+               return CM_ERROR_INVAL;
        else if (NTProtoIndex != -1) {
-               smb_SetSMBParm(outp, 0, protoIndex);
-                smb_SetSMBParmByte(outp, 1, 0);        /* share level security, no passwd encrypt */
-                smb_SetSMBParm(outp, 1, 8);    /* max multiplexed requests */
-                smb_SetSMBParm(outp, 2, 100);  /* max VCs per consumer/server connection */
-                smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE); /* xmit buffer size */
-               smb_SetSMBParmLong(outp, 5, 65536);     /* raw buffer size */
-                smb_SetSMBParm(outp, 7, 1);    /* next 2: session key */
-                smb_SetSMBParm(outp, 8, 1);
+        smb_SetSMBParm(outp, 0, protoIndex);
+               if (smb_authType != SMB_AUTH_NONE) {
+                       smb_SetSMBParmByte(outp, 1,
+                               NEGOTIATE_SECURITY_USER_LEVEL |
+                               NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */
+               } else {
+            smb_SetSMBParmByte(outp, 1, 0); /* share level auth with plaintext password. */
+               }
+        smb_SetSMBParm(outp, 1, smb_maxMpxRequests);   /* max multiplexed requests */
+        smb_SetSMBParm(outp, 2, smb_maxVCPerServer);   /* max VCs per consumer/server connection */
+        smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE);    /* xmit buffer size */
+               smb_SetSMBParmLong(outp, 5, SMB_MAXRAWSIZE);    /* raw buffer size */
+        /* The session key is not a well documented field however most clients
+         * will echo back the session key to the server.  Currently we are using
+         * the same value for all sessions.  We should generate a random value
+         * and store it into the vcp 
+         */
+        smb_SetSMBParm(outp, 7, 1);    /* next 2: session key */
+        smb_SetSMBParm(outp, 8, 1);
                /* 
                 * Tried changing the capabilities to support for W2K - defect 117695
                 * Maybe something else needs to be changed here?
@@ -1820,38 +2634,109 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                  else 
                  smb_SetSMBParmLong(outp, 9, 0x251);
                  */
-               smb_SetSMBParmLong(outp, 9, 0x251);     /* Capabilities: *
-                                                * 32-bit error codes *
-                                                * and NT Find *
-                                                * and NT SMB's *
-                                                * and raw mode */
-                smb_SetSMBParmLong(outp, 11, 0);/* XXX server time: do we need? */
-                smb_SetSMBParmLong(outp, 13, 0);/* XXX server date: do we need? */
-                smb_SetSMBParm(outp, 15, 0);   /* XXX server tzone: do we need? */
-               smb_SetSMBParmByte(outp, 16, 0);/* Encryption key length */
-                smb_SetSMBDataLength(outp, 0); /* perhaps should specify 8 bytes anyway */
+               /* Capabilities: *
+                * 32-bit error codes *
+                * and NT Find *
+                * and NT SMB's *
+                * and raw mode */
+        caps = NTNEGOTIATE_CAPABILITY_NTSTATUS |
+                          NTNEGOTIATE_CAPABILITY_NTFIND |
+               NTNEGOTIATE_CAPABILITY_RAWMODE |
+                          NTNEGOTIATE_CAPABILITY_NTSMB;
+
+        if ( smb_authType == SMB_AUTH_EXTENDED )
+            caps |= NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY;
+
+        smb_SetSMBParmLong(outp, 9, caps);
+               time(&unixTime);
+               smb_SearchTimeFromUnixTime(&dosTime, unixTime);
+               smb_SetSMBParmLong(outp, 11, LOWORD(dosTime));/* server time */
+               smb_SetSMBParmLong(outp, 13, HIWORD(dosTime));/* server date */
+
+               GetTimeZoneInformation(&tzi);
+               smb_SetSMBParm(outp, 15, (unsigned short) tzi.Bias);    /* server tzone */
+
+               if (smb_authType == SMB_AUTH_NTLM) {
+                       smb_SetSMBParmByte(outp, 16, MSV1_0_CHALLENGE_LENGTH);/* Encryption key length */
+                       smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength);
+                       /* paste in encryption key */
+                       datap = smb_GetSMBData(outp, NULL);
+                       memcpy(datap,vcp->encKey,MSV1_0_CHALLENGE_LENGTH);
+                       /* and the faux domain name */
+                       strcpy(datap + MSV1_0_CHALLENGE_LENGTH,smb_ServerDomainName);
+               } else if ( smb_authType == SMB_AUTH_EXTENDED ) {
+            void * secBlob;
+                       int secBlobLength;
+
+                       smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */
+
+                       smb_NegotiateExtendedSecurity(&secBlob, &secBlobLength);
+
+                       smb_SetSMBDataLength(outp, secBlobLength + sizeof(smb_ServerGUID));
+                       
+                       datap = smb_GetSMBData(outp, NULL);
+                       memcpy(datap, &smb_ServerGUID, sizeof(smb_ServerGUID));
+
+                       if (secBlob) {
+                               datap += sizeof(smb_ServerGUID);
+                               memcpy(datap, secBlob, secBlobLength);
+                               free(secBlob);
+                       }
+        } else {
+                       smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */
+                       smb_SetSMBDataLength(outp, 0);   /* Perhaps we should specify 8 bytes anyway */
+               }
        }
        else if (v3ProtoIndex != -1) {
-                smb_SetSMBParm(outp, 0, protoIndex);
-                smb_SetSMBParm(outp, 1, 0);    /* share level security, no passwd encrypt */
-                smb_SetSMBParm(outp, 2, SMB_PACKETSIZE);
-                smb_SetSMBParm(outp, 3, 8);    /* max multiplexed requests */
-                smb_SetSMBParm(outp, 4, 100);  /* max VCs per consumer/server connection */
-                smb_SetSMBParm(outp, 5, 0);    /* no support of block mode for read or write */
-                smb_SetSMBParm(outp, 6, 1);    /* next 2: session key */
-                smb_SetSMBParm(outp, 7, 1);
-                smb_SetSMBParm(outp, 8, 0);    /* XXX server time: do we need? */
-                smb_SetSMBParm(outp, 9, 0);    /* XXX server date: do we need? */
-                smb_SetSMBParm(outp, 10, 0);   /* XXX server tzone: do we need? */
-                smb_SetSMBParm(outp, 11, 0);   /* resvd */
-                smb_SetSMBParm(outp, 12, 0);   /* resvd */
-                smb_SetSMBDataLength(outp, 0); /* perhaps should specify 8 bytes anyway */
-        }
-       else if (coreProtoIndex != -1) {
-                smb_SetSMBParm(outp, 0, protoIndex);
-                smb_SetSMBDataLength(outp, 0);
-        }
-        return 0;
+               smb_SetSMBParm(outp, 0, protoIndex);
+
+        /* NOTE: Extended authentication cannot be negotiated with v3
+         * therefore we fail over to NTLM 
+         */
+        if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
+                       smb_SetSMBParm(outp, 1,
+                               NEGOTIATE_SECURITY_USER_LEVEL |
+                               NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */
+               } else {
+                       smb_SetSMBParm(outp, 1, 0); /* share level auth with clear password */
+               }
+               smb_SetSMBParm(outp, 2, SMB_PACKETSIZE);
+               smb_SetSMBParm(outp, 3, smb_maxMpxRequests);    /* max multiplexed requests */
+               smb_SetSMBParm(outp, 4, smb_maxVCPerServer);    /* max VCs per consumer/server connection */
+               smb_SetSMBParm(outp, 5, 0);     /* no support of block mode for read or write */
+               smb_SetSMBParm(outp, 6, 1);     /* next 2: session key */
+               smb_SetSMBParm(outp, 7, 1);
+               time(&unixTime);
+               smb_SearchTimeFromUnixTime(&dosTime, unixTime);
+               smb_SetSMBParm(outp, 8, LOWORD(dosTime));       /* server time */
+               smb_SetSMBParm(outp, 9, HIWORD(dosTime));       /* server date */
+
+               GetTimeZoneInformation(&tzi);
+               smb_SetSMBParm(outp, 10, (unsigned short) tzi.Bias);    /* server tzone */
+
+        /* NOTE: Extended authentication cannot be negotiated with v3
+         * therefore we fail over to NTLM 
+         */
+               if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
+                       smb_SetSMBParm(outp, 11, MSV1_0_CHALLENGE_LENGTH);      /* encryption key length */
+            smb_SetSMBParm(outp, 12, 0);       /* resvd */
+                       smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength);       /* perhaps should specify 8 bytes anyway */
+                       datap = smb_GetSMBData(outp, NULL);
+                       /* paste in a new encryption key */
+                       memcpy(datap, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
+                       /* and the faux domain name */
+                       strcpy(datap + MSV1_0_CHALLENGE_LENGTH, smb_ServerDomainName);
+               } else {
+                       smb_SetSMBParm(outp, 11, 0); /* encryption key length */
+                       smb_SetSMBParm(outp, 12, 0); /* resvd */
+                       smb_SetSMBDataLength(outp, 0);
+               }
+       }
+       else if (coreProtoIndex != -1) {     /* not really supported anymore */
+               smb_SetSMBParm(outp, 0, protoIndex);
+               smb_SetSMBDataLength(outp, 0);
+       }
+       return 0;
 }
 
 void smb_Daemon(void *parmp)
@@ -1860,11 +2745,24 @@ void smb_Daemon(void *parmp)
 
        while(1) {
                count++;
-               Sleep(10000);
-               if ((count % 360) == 0)         /* every hour */
-                       smb_CalculateNowTZ();
-               /* XXX GC dir search entries */
+               thrd_Sleep(10000);
+               if ((count % 360) == 0) {       /* every hour */
+            struct tm myTime;
+                
+            /* Initialize smb_localZero */
+            myTime.tm_isdst = -1;              /* compute whether on DST or not */
+            myTime.tm_year = 70;
+            myTime.tm_mon = 0;
+            myTime.tm_mday = 1;
+            myTime.tm_hour = 0;
+            myTime.tm_min = 0;
+            myTime.tm_sec = 0;
+            smb_localZero = mktime(&myTime);
+
+            smb_CalculateNowTZ();
         }
+               /* XXX GC dir search entries */
+       }
 }
 
 void smb_WaitingLocksDaemon()
@@ -1874,14 +2772,14 @@ void smb_WaitingLocksDaemon()
        smb_vc_t *vcp;
        smb_packet_t *inp, *outp;
        NCB *ncbp;
-       long code;
+       long code = 0;
 
        while(1) {
                lock_ObtainWrite(&smb_globalLock);
                nwL = smb_allWaitingLocks;
                if (nwL == NULL) {
                        osi_SleepW((long)&smb_allWaitingLocks, &smb_globalLock);
-                       Sleep(1000);
+                       thrd_Sleep(1000);
                        continue;
                }
                else first = 1;
@@ -1894,7 +2792,7 @@ void smb_WaitingLocksDaemon()
                        nwL = (smb_waitingLock_t *) osi_QNext(&wL->q);
                        lock_ReleaseWrite(&smb_globalLock);
                        code = cm_RetryLock((cm_file_lock_t *) wL->lockp,
-                               wL->vcp->flags & SMB_VCFLAG_ALREADYDEAD);
+                                                               wL->vcp->flags & SMB_VCFLAG_ALREADYDEAD);
                        if (code == CM_ERROR_WOULDBLOCK) {
                                /* no progress */
                                if (wL->timeRemaining != 0xffffffff
@@ -1902,7 +2800,7 @@ void smb_WaitingLocksDaemon()
                                        goto endWait;
                                continue;
                        }
-endWait:
+                 endWait:
                        vcp = wL->vcp;
                        inp = wL->inp;
                        outp = wL->outp;
@@ -1931,70 +2829,74 @@ endWait:
                        FreeNCB(ncbp);
                        free(wL);
                } while (nwL);
-               Sleep(1000);
+               thrd_Sleep(1000);
        }
 }
 
 long smb_ReceiveCoreGetDiskAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       osi_Log0(afsd_logp, "SMB receive get disk attributes");
-
-        smb_SetSMBParm(outp, 0, 32000);
-        smb_SetSMBParm(outp, 1, 64);
-        smb_SetSMBParm(outp, 2, 1024);
-        smb_SetSMBParm(outp, 3, 30000);
-        smb_SetSMBParm(outp, 4, 0);
-        smb_SetSMBDataLength(outp, 0);
+       osi_Log0(smb_logp, "SMB receive get disk attributes");
+
+       smb_SetSMBParm(outp, 0, 32000);
+       smb_SetSMBParm(outp, 1, 64);
+       smb_SetSMBParm(outp, 2, 1024);
+       smb_SetSMBParm(outp, 3, 30000);
+       smb_SetSMBParm(outp, 4, 0);
+       smb_SetSMBDataLength(outp, 0);
        return 0;
 }
 
 long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *rsp)
 {
-        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;
-        cm_user_t *userp;
-        
-       osi_Log0(afsd_logp, "SMB receive tree connect");
+       char *tp;
+       char *pathp;
+       char *passwordp;
+       cm_user_t *userp;
+
+       osi_Log0(smb_logp, "SMB receive tree connect");
 
        /* parse input parameters */
        tp = smb_GetSMBData(inp, NULL);
        pathp = smb_ParseASCIIBlock(tp, &tp);
-        passwordp = smb_ParseASCIIBlock(tp, &tp);
+       passwordp = smb_ParseASCIIBlock(tp, &tp);
        tp = strrchr(pathp, '\\');
-        if (!tp)
+       if (!tp)
                return CM_ERROR_BADSMB;
-        strcpy(shareName, tp+1);
+       strcpy(shareName, tp+1);
 
-        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);
+    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;
+       lock_ObtainMutex(&tidp->mx);
+       tidp->userp = userp;
        tidp->pathname = sharePath;
-        lock_ReleaseMutex(&tidp->mx);
-        smb_ReleaseTID(tidp);
+       lock_ReleaseMutex(&tidp->mx);
+       smb_ReleaseTID(tidp);
 
-        smb_SetSMBParm(rsp, 0, SMB_PACKETSIZE);
-        smb_SetSMBParm(rsp, 1, newTid);
-        smb_SetSMBDataLength(rsp, 0);
-        
-        osi_Log1(afsd_logp, "SMB tree connect created ID %d", newTid);
-        return 0;
+       smb_SetSMBParm(rsp, 0, SMB_PACKETSIZE);
+       smb_SetSMBParm(rsp, 1, newTid);
+       smb_SetSMBDataLength(rsp, 0);
+
+       osi_Log1(smb_logp, "SMB tree connect created ID %d", newTid);
+       return 0;
 }
 
 unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp)
@@ -2002,16 +2904,16 @@ unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengt
        int tlen;
 
        if (*inp++ != 0x1) return NULL;
-        tlen = inp[0] + (inp[1]<<8);
-        inp += 2;              /* skip length field */
+       tlen = inp[0] + (inp[1]<<8);
+       inp += 2;               /* skip length field */
         
-        if (chainpp) {
+       if (chainpp) {
                *chainpp = inp + tlen;
-        }
+       }       
         
-        if (lengthp) *lengthp = tlen;
+       if (lengthp) *lengthp = tlen;
         
-        return inp;
+       return inp;
 }
 
 /* set maskp to the mask part of the incoming path.
@@ -2022,10 +2924,10 @@ unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengt
 int smb_Get8Dot3MaskFromPath(unsigned char *maskp, unsigned char *pathp)
 {
        char *tp;
-        char *up;
-        int i;
-        int tc;
-        int valid8Dot3;
+       char *up;
+       int i;
+       int tc;
+       int valid8Dot3;
 
        /* starts off valid */
        valid8Dot3 = 1;
@@ -2034,68 +2936,78 @@ int smb_Get8Dot3MaskFromPath(unsigned char *maskp, unsigned char *pathp)
        memset(maskp, ' ', 11);
 
        /* find last backslash, or use whole thing if there is none */
-        tp = strrchr(pathp, '\\');
-        if (!tp) tp = pathp;
-        else tp++;     /* skip slash */
+       tp = strrchr(pathp, '\\');
+       if (!tp) tp = pathp;
+       else tp++;      /* skip slash */
         
        up = maskp;
 
        /* names starting with a dot are illegal */
        if (*tp == '.') valid8Dot3 = 0;
 
-        for(i=0;; i++) {
-               tc = *tp++;
-                if (tc == 0) return valid8Dot3;
-                if (tc == '.' || tc == '"') break;
-                if (i < 8) *up++ = tc;
-                else valid8Dot3 = 0;
-        }
-        
-        /* if we get here, tp point after the dot */
-        up = maskp+8;  /* ext goes here */
-        for(i=0;;i++) {
+    for(i=0;; i++) {
                tc = *tp++;
-                if (tc == 0) return valid8Dot3;
-               
-                /* too many dots */
-                if (tc == '.' || tc == '"') valid8Dot3 = 0;
-
-               /* copy extension if not too long */
-                if (i < 3) *up++ = tc;
-                else valid8Dot3 = 0;
-        }
+        if (tc == 0) return valid8Dot3;
+        if (tc == '.' || tc == '"') break;
+        if (i < 8) *up++ = tc;
+        else valid8Dot3 = 0;
+    }
+        
+    /* if we get here, tp point after the dot */
+    up = maskp+8;      /* ext goes here */
+    for(i=0;;i++) {
+        tc = *tp++;
+        if (tc == 0) 
+                       return valid8Dot3;
+
+        /* too many dots */
+        if (tc == '.' || tc == '"') 
+                       valid8Dot3 = 0;
+
+        /* copy extension if not too long */
+        if (i < 3) 
+                       *up++ = tc;
+        else 
+                       valid8Dot3 = 0;
+    }   
+
+    /* unreachable */
 }
 
 int smb_Match8Dot3Mask(char *unixNamep, char *maskp)
 {
        char umask[11];
-        int valid;
-        int i;
-        char tc1;
-        char tc2;
-        char *tp1;
-        char *tp2;
-        
+       int valid;
+       int i;
+       char tc1;
+       char tc2;
+       char *tp1;
+       char *tp2;
+
        /* XXX redo this, calling smb_V3MatchMask with a converted mask */
 
-        valid = smb_Get8Dot3MaskFromPath(umask, unixNamep);
-        if (!valid) return 0;
+       valid = smb_Get8Dot3MaskFromPath(umask, unixNamep);
+       if (!valid) 
+               return 0;
  
        /* otherwise, we have a valid 8.3 name; see if we have a match,
-         * treating '?' as a wildcard in maskp (but not in the file name).
-         */
+        * treating '?' as a wildcard in maskp (but not in the file name).
+        */
        tp1 = umask;    /* real name, in mask format */
-        tp2 = maskp;   /* mask, in mask format */
+       tp2 = maskp;    /* mask, in mask format */
        for(i=0; i<11; i++) {
                tc1 = *tp1++;   /* char from real name */
-                tc2 = *tp2++;  /* char from mask */
+               tc2 = *tp2++;   /* char from mask */
                tc1 = (char) cm_foldUpper[(unsigned char)tc1];
                tc2 = (char) cm_foldUpper[(unsigned char)tc2];
-               if (tc1 == tc2) continue;
-               if (tc2 == '?' && tc1 != ' ') continue;
-               if (tc2 == '>') continue;
+               if (tc1 == tc2) 
+                       continue;
+               if (tc2 == '?' && tc1 != ' ') 
+                       continue;
+               if (tc2 == '>') 
+                       continue;
                return 0;
-        }
+       }
 
        /* we got a match */
        return 1;
@@ -2105,262 +3017,269 @@ char *smb_FindMask(char *pathp)
 {
        char *tp;
         
-        tp = strrchr(pathp, '\\');     /* find last slash */
+       tp = strrchr(pathp, '\\');      /* find last slash */
 
-        if (tp) return tp+1;   /* skip the slash */
-        else return pathp;     /* no slash, return the entire path */
+       if (tp) 
+               return tp+1;    /* skip the slash */
+       else 
+               return pathp;   /* no slash, return the entire path */
 }
 
 long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        unsigned char *pathp;
-        unsigned char *tp;
-        unsigned char mask[11];
-        unsigned char *statBlockp;
+       unsigned char *tp;
+       unsigned char mask[11];
+       unsigned char *statBlockp;
        unsigned char initStatBlock[21];
        int statLen;
         
-       osi_Log0(afsd_logp, "SMB receive search volume");
+       osi_Log0(smb_logp, "SMB receive search volume");
 
        /* pull pathname and stat block out of request */
        tp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(tp, &tp);
-        osi_assert(pathp != NULL);
-        statBlockp = smb_ParseVblBlock(tp, &tp, &statLen);
-        osi_assert(statBlockp != NULL);
+       pathp = smb_ParseASCIIBlock(tp, (char **) &tp);
+       osi_assert(pathp != NULL);
+       statBlockp = smb_ParseVblBlock(tp, (char **) &tp, &statLen);
+       osi_assert(statBlockp != NULL);
        if (statLen == 0) {
                statBlockp = initStatBlock;
                statBlockp[0] = 8;
        }
         
        /* for returning to caller */
-        smb_Get8Dot3MaskFromPath(mask, pathp);
+       smb_Get8Dot3MaskFromPath(mask, pathp);
         
        smb_SetSMBParm(outp, 0, 1);             /* we're returning one entry */
-        tp = smb_GetSMBData(outp, NULL);
-        *tp++ = 5;
-        *tp++ = 43;    /* bytes in a dir entry */
-        *tp++ = 0;     /* high byte in counter */
-        
-        /* now marshall the dir entry, starting with the search status */
-        *tp++ = statBlockp[0];         /* Reserved */
-        memcpy(tp, mask, 11); tp += 11;        /* FileName */
+       tp = smb_GetSMBData(outp, NULL);
+       *tp++ = 5;
+       *tp++ = 43;     /* bytes in a dir entry */
+       *tp++ = 0;      /* high byte in counter */
+
+       /* now marshall the dir entry, starting with the search status */
+       *tp++ = statBlockp[0];          /* Reserved */
+       memcpy(tp, mask, 11); tp += 11; /* FileName */
 
        /* now pass back server use info, with 1st byte non-zero */
-        *tp++ = 1;
-        memset(tp, 0, 4); tp += 4;     /* reserved for server use */
-        
-        memcpy(tp, statBlockp+17, 4); tp += 4; /* reserved for consumer */
-        
-        *tp++ = 0x8;           /* attribute: volume */
+       *tp++ = 1;
+       memset(tp, 0, 4); tp += 4;      /* reserved for server use */
+
+       memcpy(tp, statBlockp+17, 4); tp += 4;  /* reserved for consumer */
+
+       *tp++ = 0x8;            /* attribute: volume */
 
        /* copy out time */
-        *tp++ = 0;
-        *tp++ = 0;
-        
-        /* copy out date */
-        *tp++ = 18;
-        *tp++ = 178;
-        
+       *tp++ = 0;
+       *tp++ = 0;
+
+       /* copy out date */
+       *tp++ = 18;
+       *tp++ = 178;
+
        /* 4 byte file size */
-        *tp++ = 0;
-        *tp++ = 0;
-        *tp++ = 0;
-        *tp++ = 0;
+       *tp++ = 0;
+       *tp++ = 0;
+       *tp++ = 0;
+       *tp++ = 0;
 
        /* finally, null-terminated 8.3 pathname, which we set to AFS */
-        memset(tp, ' ', 13);
-        strcpy(tp, "AFS");
-        
-        /* set the length of the data part of the packet to 43 + 3, for the dir
-         * entry plus the 5 and the length fields.
-         */
-        smb_SetSMBDataLength(outp, 46);
+       memset(tp, ' ', 13);
+       strcpy(tp, "AFS");
+
+       /* set the length of the data part of the packet to 43 + 3, for the dir
+        * entry plus the 5 and the length fields.
+        */
+       smb_SetSMBDataLength(outp, 46);
        return 0;
 }
 
 long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
        cm_user_t *userp, cm_req_t *reqp)
 {
-       long code;
-        cm_scache_t *scp;
-        char *dptr;
-        long dosTime;
-        u_short shortTemp;
-        char attr;
-        smb_dirListPatch_t *patchp;
-        smb_dirListPatch_t *npatchp;
-        
-        for(patchp = *dirPatchespp; patchp; patchp =
-               (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
+       long code = 0;
+       cm_scache_t *scp;
+       char *dptr;
+       long dosTime;
+       u_short shortTemp;
+       char attr;
+       smb_dirListPatch_t *patchp;
+       smb_dirListPatch_t *npatchp;
+
+       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;
-                }
+               }
                dptr = patchp->dptr;
 
                attr = smb_Attributes(scp);
-                *dptr++ = attr;
+        /* check hidden attribute (the flag is only ON when dot file hiding is on ) */
+        if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+            attr |= SMB_ATTR_HIDDEN;
+        *dptr++ = attr;
 
                /* get dos time */
-                smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+               smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
                 
-                /* copy out time */
-                shortTemp = dosTime & 0xffff;
+               /* copy out time */
+               shortTemp = dosTime & 0xffff;
                *((u_short *)dptr) = shortTemp;
-                dptr += 2;
+               dptr += 2;
 
                /* and copy out date */
-                shortTemp = (dosTime>>16) & 0xffff;
+               shortTemp = (dosTime>>16) & 0xffff;
                *((u_short *)dptr) = shortTemp;
-                dptr += 2;
+               dptr += 2;
                 
-                /* copy out file length */
+               /* copy out file length */
                *((u_long *)dptr) = scp->length.LowPart;
-                dptr += 4;
-                lock_ReleaseMutex(&scp->mx);
-                cm_ReleaseSCache(scp);
+               dptr += 4;
+               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;
 }
 
 long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        int attribute;
-        long nextCookie;
-        char *tp;
-        long code;
-        char *pathp;
-        cm_dirEntry_t *dep;
-        int maxCount;
-        smb_dirListPatch_t *dirListPatchesp;
-        smb_dirListPatch_t *curPatchp;
-        long dataLength;
-        cm_buf_t *bufferp;
-        long temp;
-        osi_hyper_t dirLength;
-        osi_hyper_t bufferOffset;
-        osi_hyper_t curOffset;
-        osi_hyper_t thyper;
-        unsigned char *inCookiep;
-        smb_dirSearch_t *dsp;
-        cm_scache_t *scp;
-        long entryInDir;
-        long entryInBuffer;
-        unsigned long clientCookie;
+       long nextCookie;
+       char *tp;
+       long code = 0;
+       char *pathp;
+       cm_dirEntry_t *dep;
+       int maxCount;
+       smb_dirListPatch_t *dirListPatchesp;
+       smb_dirListPatch_t *curPatchp;
+       int dataLength;
+       cm_buf_t *bufferp;
+       long temp;
+       osi_hyper_t dirLength;
+       osi_hyper_t bufferOffset;
+       osi_hyper_t curOffset;
+       osi_hyper_t thyper;
+       unsigned char *inCookiep;
+       smb_dirSearch_t *dsp;
+       cm_scache_t *scp;
+       long entryInDir;
+       long entryInBuffer;
+       unsigned long clientCookie;
        cm_pageHeader_t *pageHeaderp;
-        cm_user_t *userp = NULL;
-        int slotInPage;
+       cm_user_t *userp = NULL;
+       int slotInPage;
        char shortName[13];
        char *actualName;
        char *shortNameEnd;
-        char mask[11];
-        int returnedNames;
-        long nextEntryCookie;
-        int numDirChunks;              /* # of 32 byte dir chunks in this entry */
-        char resByte;                  /* reserved byte from the cookie */
-        char *op;                      /* output data ptr */
-        char *origOp;                  /* original value of op */
-        cm_space_t *spacep;            /* for pathname buffer */
-        int starPattern;
+       char mask[11];
+       int returnedNames;
+       long nextEntryCookie;
+       int numDirChunks;               /* # of 32 byte dir chunks in this entry */
+       char resByte;                   /* reserved byte from the cookie */
+       char *op;                       /* output data ptr */
+       char *origOp;                   /* original value of op */
+       cm_space_t *spacep;             /* for pathname buffer */
+       int starPattern;
        int rootPath = 0;
-        int caseFold;
+       int caseFold;
        char *tidPathp;
-        cm_req_t req;
+       cm_req_t req;
+       cm_fid_t fid;
+       int fileType;
 
        cm_InitReq(&req);
 
-        maxCount = smb_GetSMBParm(inp, 0);
+       maxCount = smb_GetSMBParm(inp, 0);
 
-        dirListPatchesp = NULL;
+       dirListPatchesp = NULL;
         
-               caseFold = CM_FLAG_CASEFOLD;
+       caseFold = CM_FLAG_CASEFOLD;
 
        tp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(tp, &tp);
-        inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
-        
-        /* bail out if request looks bad */
-        if (!tp || !pathp) {
-                return CM_ERROR_BADSMB;
-        }
+       pathp = smb_ParseASCIIBlock(tp, &tp);
+       inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
+
+       /* bail out if request looks bad */
+       if (!tp || !pathp) {
+               return CM_ERROR_BADSMB;
+       }
 
        /* We can handle long names */
        if (vcp->flags & SMB_VCFLAG_USENT)
                ((smb_t *)outp)->flg2 |= 0x40;  /* IS_LONG_NAME */
-        
+
        /* make sure we got a whole search status */
        if (dataLength < 21) {
-               nextCookie = 0;         /* start at the beginning of the dir */
-                resByte = 0;
-                clientCookie = 0;
+               nextCookie = 0;         /* start at the beginning of the dir */
+               resByte = 0;
+               clientCookie = 0;
                attribute = smb_GetSMBParm(inp, 1);
 
                /* handle volume info in another function */
                if (attribute & 0x8)
                        return smb_ReceiveCoreSearchVolume(vcp, inp, outp);
 
-               osi_Log2(afsd_logp, "SMB receive search dir count %d |%s|",
-                        maxCount, osi_LogSaveString(afsd_logp, pathp));
+               osi_Log2(smb_logp, "SMB receive search dir count %d [%s]",
+                                maxCount, osi_LogSaveString(smb_logp, pathp));
 
                if (*pathp == 0) {      /* null pathp, treat as root dir */
-                       if (!(attribute & 0x10))        /* exclude dirs */
+                       if (!(attribute & SMB_ATTR_DIRECTORY))  /* exclude dirs */
                                return CM_ERROR_NOFILES;
                        rootPath = 1;
                }
 
-                dsp = smb_NewDirSearch(0);
+               dsp = smb_NewDirSearch(0);
                dsp->attribute = attribute;
-                smb_Get8Dot3MaskFromPath(mask, pathp);
+               smb_Get8Dot3MaskFromPath(mask, pathp);
                memcpy(dsp->mask, mask, 11);
 
                /* track if this is likely to match a lot of entries */
-                if (smb_IsStarMask(mask)) starPattern = 1;
-                else starPattern = 0;
-       }
+               if (smb_IsStarMask(mask)) starPattern = 1;
+               else starPattern = 0;
+       }       
        else {
                /* pull the next cookie value out of the search status block */
-                nextCookie = inCookiep[13] + (inCookiep[14]<<8) + (inCookiep[15]<<16)
-                       + (inCookiep[16]<<24);
+               nextCookie = inCookiep[13] + (inCookiep[14]<<8) + (inCookiep[15]<<16)
+                       + (inCookiep[16]<<24);
                dsp = smb_FindDirSearch(inCookiep[12]);
                if (!dsp) {
                        /* can't find dir search status; fatal error */
                        return CM_ERROR_BADFD;
-                }
+               }
                attribute = dsp->attribute;
                resByte = inCookiep[0];
 
                /* copy out client cookie, in host byte order.  Don't bother
-                 * interpreting it, since we're just passing it through, anyway.
-                 */
+                * interpreting it, since we're just passing it through, anyway.
+                */
                memcpy(&clientCookie, &inCookiep[17], 4);
 
                memcpy(mask, dsp->mask, 11);
 
                /* assume we're doing a star match if it has continued for more
                 * than one call.
-                 */
-                starPattern = 1;
-        }
+                */
+               starPattern = 1;
+       }
 
-       osi_Log3(afsd_logp, "SMB dir search cookie 0x%x, connection %d, attr 0x%x",
-               nextCookie, dsp->cookie, attribute);
+       osi_Log3(smb_logp, "SMB dir search cookie 0x%x, connection %d, attr 0x%x",
+                        nextCookie, dsp->cookie, attribute);
 
        userp = smb_GetUser(vcp, inp);
 
@@ -2368,27 +3287,27 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
        lock_ObtainMutex(&dsp->mx);
        if (dsp->scp) {
                scp = dsp->scp;
-                cm_HoldSCache(scp);
-                code = 0;
-        }
-        else {
+               cm_HoldSCache(scp);
+               code = 0;
+       }
+       else {
                spacep = inp->spacep;
-               smb_StripLastComponent(spacep->data, NULL, pathp);
-                lock_ReleaseMutex(&dsp->mx);
+               smb_StripLastComponent(spacep->data, NULL, pathp);
+               lock_ReleaseMutex(&dsp->mx);
                tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
-               code = cm_NameI(cm_rootSCachep, spacep->data,
-                       caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp);
-                lock_ObtainMutex(&dsp->mx);
+               code = cm_NameI(cm_rootSCachep, spacep->data,
+                                               caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp);
+               lock_ObtainMutex(&dsp->mx);
                if (code == 0) {
                        if (dsp->scp != 0) cm_ReleaseSCache(dsp->scp);
                        dsp->scp = scp;
                        /* we need one hold for the entry we just stored into,
-                         * 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);
+                        * 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)) {
@@ -2397,179 +3316,180 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                        }
                        lock_ReleaseMutex(&scp->mx);
                }
-        }
+       }
        lock_ReleaseMutex(&dsp->mx);
-        if (code) {
+       if (code) {
                cm_ReleaseUser(userp);
                smb_DeleteDirSearch(dsp);
                smb_ReleaseDirSearch(dsp);
-                return code;
-        }
+               return code;
+       }
 
        /* reserves space for parameter; we'll adjust it again later to the
-         * real count of the # of entries we returned once we've actually
-         * assembled the directory listing.
-         */
+        * real count of the # of entries we returned once we've actually
+        * assembled the directory listing.
+        */
        smb_SetSMBParm(outp, 0, 0);
        
-        /* 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);
+               cm_ReleaseSCache(scp);
+               cm_ReleaseUser(userp);
                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;
+       dirLength = scp->length;
+       bufferp = NULL;
+       bufferOffset.LowPart = bufferOffset.HighPart = 0;
+       curOffset.HighPart = 0;
+       curOffset.LowPart = nextCookie;
        origOp = op = smb_GetSMBData(outp, NULL);
-        /* and write out the basic header */
-        *op++ = 5;             /* variable block */
-        op += 2;               /* skip vbl block length; we'll fill it in later */
-        code = 0;
-        returnedNames = 0;
-        while (1) {
+       /* and write out the basic header */
+       *op++ = 5;              /* variable block */
+       op += 2;                /* skip vbl block length; we'll fill it in later */
+       code = 0;
+       returnedNames = 0;
+       while (1) {
                /* 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;
-                }
+                       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;
+               /* 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 returned all the names that will fit in the
-                 * response packet.
-                 */
-               if (returnedNames >= maxCount) break;
-                
-                /* check if we've passed the dir's EOF */
-                if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) break;
+                * response packet.
+                */
+               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.
+               /* check if we've passed the dir's EOF */
+               if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) 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)) {
+               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) {
+                        * the status info for files in the dir.
+                        */
+                       if (starPattern) {
                                smb_ApplyDirListPatches(&dirListPatchesp, userp,
-                                                       &req);
+                                                                               &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);
+                                       /* 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);
+                                                                 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);
-                                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.
-                 */
+                * 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.
+                */
                temp = curOffset.LowPart & (buf_bufferSize - 1);  /* only look intra-buffer */
-                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)))) {
+                * 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,
+               /* 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.
-                 */
+                *
+                * XXXX Probably should do more sanity checking.
+                */
                numDirChunks = cm_NameEntries(dep->name, NULL);
                
-                /* compute the offset of the cookie representing the next entry */
-                nextEntryCookie = curOffset.LowPart + (CM_DIR_CHUNKSIZE * numDirChunks);
+               /* compute the offset of the cookie representing the next entry */
+               nextEntryCookie = curOffset.LowPart + (CM_DIR_CHUNKSIZE * numDirChunks);
 
                /* Compute 8.3 name if necessary */
                actualName = dep->name;
@@ -2578,20 +3498,43 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                        actualName = shortName;
                }
 
-                if (dep->fid.vnode != 0 && smb_Match8Dot3Mask(actualName, mask)) {
+               if (dep->fid.vnode != 0 && smb_Match8Dot3Mask(actualName, mask)) {
                        /* this is one of the entries to use: it is not deleted
                         * and it matches the star pattern we're looking for.
-                         */
+                        */
+
+                       /* Eliminate entries that don't match requested
+                          attributes */
+
+                       /* no hidden files */
+                       if(smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) && smb_IsDotFile(actualName))
+                               goto nextEntry;
+
+                       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_ReceiveCoreSearchDir: file %s "
+                                                 "has filetype %d", dep->name,
+                                                 fileType);
+                               if (fileType == CM_SCACHETYPE_DIRECTORY)
+                                       goto nextEntry;
+                       }
+
                        *op++ = resByte;
-                        memcpy(op, mask, 11); op += 11;
-                        *op++ = (char) dsp->cookie;    /* they say it must be non-zero */
-                        *op++ = nextEntryCookie & 0xff;
-                        *op++ = (nextEntryCookie>>8) & 0xff;
-                        *op++ = (nextEntryCookie>>16) & 0xff;
-                        *op++ = (nextEntryCookie>>24) & 0xff;
-                        memcpy(op, &clientCookie, 4); op += 4;
-                        
-                        /* now we emit the attribute.  This is sort of tricky,
+                       memcpy(op, mask, 11); op += 11;
+                       *op++ = (char) dsp->cookie;     /* they say it must be non-zero */
+                       *op++ = nextEntryCookie & 0xff;
+                       *op++ = (nextEntryCookie>>8) & 0xff;
+                       *op++ = (nextEntryCookie>>16) & 0xff;
+                       *op++ = (nextEntryCookie>>24) & 0xff;
+                       memcpy(op, &clientCookie, 4); op += 4;
+
+                       /* now we emit the attribute.  This is sort of 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
@@ -2603,26 +3546,36 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                         * 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.
-                         */
+                        */
                        curPatchp = malloc(sizeof(*curPatchp));
-                        osi_QAdd((osi_queue_t **) &dirListPatchesp, &curPatchp->q);
-                        curPatchp->dptr = op;
+                       osi_QAdd((osi_queue_t **) &dirListPatchesp, &curPatchp->q);
+                       curPatchp->dptr = op;
                        curPatchp->fid.cell = scp->fid.cell;
-                        curPatchp->fid.volume = scp->fid.volume;
-                        curPatchp->fid.vnode = ntohl(dep->fid.vnode);
-                        curPatchp->fid.unique = ntohl(dep->fid.unique);
+                       curPatchp->fid.volume = scp->fid.volume;
+                       curPatchp->fid.vnode = ntohl(dep->fid.vnode);
+                       curPatchp->fid.unique = ntohl(dep->fid.unique);
+
+                       /* do hidden attribute here since name won't be around when applying
+                        * dir list patches
+                        */
+
+                       if ( smb_hideDotFiles && smb_IsDotFile(actualName) )
+                               curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE;
+                       else
+                               curPatchp->flags = 0;
+
                        op += 9;        /* skip attr, time, date and size */
-                        
+
                        /* zero out name area.  The spec says to pad with
                         * spaces, but Samba doesn't, and neither do we.
                         */
                        memset(op, 0, 13);
 
-                        /* finally, we get to copy out the name; we know that
+                       /* finally, we get to copy out the name; we know that
                         * it fits in 8.3 or the pattern wouldn't match, but it
                         * never hurts to be sure.
-                         */
-                        strncpy(op, actualName, 13);
+                        */
+                       strncpy(op, actualName, 13);
 
                        /* Uppercase if requested by client */
                        if ((((smb_t *)inp)->flg2 & 1) == 0)
@@ -2630,31 +3583,31 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 
                        op += 13;
 
-                       /* now, adjust the # of entries copied */
-                       returnedNames++;
+                       /* now, adjust the # of entries copied */
+                       returnedNames++;
                }       /* if we're including this name */
                 
-nextEntry:
-                /* and adjust curOffset to be where the new cookie is */
+         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 */
+               thyper.LowPart = CM_DIR_CHUNKSIZE * numDirChunks;
+               curOffset = LargeIntegerAdd(thyper, curOffset);
+       }               /* while copying data for dir listing */
 
        /* 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_ApplyDirListPatches(&dirListPatchesp, userp, &req);
+        * will be empty, but better safe (and freeing everything) than sorry.
+        */
+       smb_ApplyDirListPatches(&dirListPatchesp, userp, &req);
 
        /* special return code for unsuccessful search */
        if (code == 0 && dataLength < 21 && returnedNames == 0)
                code = CM_ERROR_NOFILES;
 
-       osi_Log2(afsd_logp, "SMB search dir done, %d names, code %d",
+       osi_Log2(smb_logp, "SMB search dir done, %d names, code %d",
                 returnedNames, code);
 
        if (code != 0) {
@@ -2665,26 +3618,26 @@ nextEntry:
                return code;
        }
 
-        /* finalize the output buffer */
-        smb_SetSMBParm(outp, 0, returnedNames);
+       /* finalize the output buffer */
+       smb_SetSMBParm(outp, 0, returnedNames);
        temp = (long) (op - origOp);
-        smb_SetSMBDataLength(outp, temp);
+       smb_SetSMBDataLength(outp, temp);
 
        /* the data area is a variable block, which has a 5 (already there)
         * followed by the length of the # of data bytes.  We now know this to
         * be "temp," although that includes the 3 bytes of vbl block header.
         * Deduct for them and fill in the length field.
-         */
+        */
        temp -= 3;              /* deduct vbl block info */
-        osi_assert(temp == (43 * returnedNames));
-        origOp[1] = temp & 0xff;
-        origOp[2] = (temp>>8) & 0xff;
-        if (returnedNames == 0) smb_DeleteDirSearch(dsp);
-        smb_ReleaseDirSearch(dsp);
-        cm_ReleaseSCache(scp);
-        cm_ReleaseUser(userp);
-        return code;
-}
+       osi_assert(temp == (43 * returnedNames));
+       origOp[1] = temp & 0xff;
+       origOp[2] = (temp>>8) & 0xff;
+       if (returnedNames == 0) smb_DeleteDirSearch(dsp);
+       smb_ReleaseDirSearch(dsp);
+       cm_ReleaseSCache(scp);
+       cm_ReleaseUser(userp);
+       return code;
+}      
 
 /* verify that this is a valid path to a directory.  I don't know why they
  * don't use the get file attributes call.
@@ -2692,76 +3645,76 @@ nextEntry:
 long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-        long code;
-        cm_scache_t *rootScp;
+       long code = 0;
+       cm_scache_t *rootScp;
        cm_scache_t *newScp;
-        cm_user_t *userp;
-        unsigned int attrs;
-        int caseFold;
+       cm_user_t *userp;
+       unsigned int attrs;
+       int caseFold;
        char *tidPathp;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-        pathp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(pathp, NULL);
-       osi_Log1(afsd_logp, "SMB receive check path %s",
-                       osi_LogSaveString(afsd_logp, pathp));
-        
-        if (!pathp) {
+       pathp = smb_GetSMBData(inp, NULL);
+       pathp = smb_ParseASCIIBlock(pathp, NULL);
+       osi_Log1(smb_logp, "SMB receive check path %s",
+                         osi_LogSaveString(smb_logp, pathp));
+
+       if (!pathp) {
                return CM_ERROR_BADFD;
        }
         
-        rootScp = cm_rootSCachep;
+       rootScp = cm_rootSCachep;
         
        userp = smb_GetUser(vcp, inp);
 
-               caseFold = CM_FLAG_CASEFOLD;
+       caseFold = CM_FLAG_CASEFOLD;
 
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
-        code = cm_NameI(rootScp, pathp,
-                       caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
-                       userp, tidPathp, &req, &newScp);
+       code = cm_NameI(rootScp, pathp,
+                                        caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
+                                        userp, tidPathp, &req, &newScp);
 
-        if (code) {
+       if (code) {
                cm_ReleaseUser(userp);
-                return code;
-        }
+               return code;
+       }
         
        /* now lock the vnode with a callback; returns with newScp locked */
        lock_ObtainMutex(&newScp->mx);
-        code = cm_SyncOp(newScp, NULL, userp, &req, PRSFS_LOOKUP,
-               CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
-        if (code && code != CM_ERROR_NOACCESS) {
+       code = cm_SyncOp(newScp, NULL, userp, &req, PRSFS_LOOKUP,
+                                         CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
+       if (code && code != CM_ERROR_NOACCESS) {
                lock_ReleaseMutex(&newScp->mx);
-                cm_ReleaseSCache(newScp);
-                cm_ReleaseUser(userp);
-                return code;
-        }
+               cm_ReleaseSCache(newScp);
+               cm_ReleaseUser(userp);
+               return code;
+       }
 
        attrs = smb_Attributes(newScp);
 
        if (!(attrs & 0x10))
-               code = CM_ERROR_NOTDIR;
+               code = CM_ERROR_NOTDIR;
 
-        lock_ReleaseMutex(&newScp->mx);
-        
-        cm_ReleaseSCache(newScp);
-        cm_ReleaseUser(userp);
-        return code;
-}
+       lock_ReleaseMutex(&newScp->mx);
+
+       cm_ReleaseSCache(newScp);
+       cm_ReleaseUser(userp);
+       return code;
+}      
 
 long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-        long code;
-        cm_scache_t *rootScp;
-        unsigned short attribute;
-        cm_attr_t attr;
+       long code = 0;
+       cm_scache_t *rootScp;
+       unsigned short attribute;
+       cm_attr_t attr;
        cm_scache_t *newScp;
-        long dosTime;
-        cm_user_t *userp;
-        int caseFold;
+       long dosTime;
+       cm_user_t *userp;
+       int caseFold;
        char *tidPathp;
        cm_req_t req;
 
@@ -2769,46 +3722,46 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 
        /* decode basic attributes we're passed */
        attribute = smb_GetSMBParm(inp, 0);
-        dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
+       dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
 
-        pathp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(pathp, NULL);
+       pathp = smb_GetSMBData(inp, NULL);
+       pathp = smb_ParseASCIIBlock(pathp, NULL);
         
-        if (!pathp) {
+       if (!pathp) {
                return CM_ERROR_BADSMB;
        }
         
-       osi_Log2(afsd_logp, "SMB receive setfile attributes time %d, attr 0x%x",
-               dosTime, attribute);
+       osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x",
+                        dosTime, attribute);
 
-        rootScp = cm_rootSCachep;
+       rootScp = cm_rootSCachep;
         
        userp = smb_GetUser(vcp, inp);
 
        caseFold = CM_FLAG_CASEFOLD;
 
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
-        code = cm_NameI(rootScp, pathp, caseFold | CM_FLAG_FOLLOW, userp,
-                       tidPathp, &req, &newScp);
+       code = cm_NameI(rootScp, pathp, caseFold | CM_FLAG_FOLLOW, userp,
+                                       tidPathp, &req, &newScp);
 
-        if (code) {
-                cm_ReleaseUser(userp);
-                return code;
-        }
+       if (code) {
+               cm_ReleaseUser(userp);
+               return code;
+       }
        
        /* now lock the vnode with a callback; returns with newScp locked; we
         * need the current status to determine what the new status is, in some
         * cases.
-         */
+        */
        lock_ObtainMutex(&newScp->mx);
-        code = cm_SyncOp(newScp, NULL, userp, &req, 0,
-               CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
-        if (code) {
+       code = cm_SyncOp(newScp, NULL, userp, &req, 0,
+                                        CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
+       if (code) {
                lock_ReleaseMutex(&newScp->mx);
-                cm_ReleaseSCache(newScp);
-                cm_ReleaseUser(userp);
-                return code;
-        }
+               cm_ReleaseSCache(newScp);
+               cm_ReleaseUser(userp);
+               return code;
+       }
 
        /* Check for RO volume */
        if (newScp->flags & CM_SCACHEFLAG_RO) {
@@ -2821,43 +3774,43 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
        /* prepare for setattr call */
        attr.mask = 0;
        if (dosTime != 0) {
-               attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
-               smb_UnixTimeFromDosUTime(&attr.clientModTime, dosTime);
+               attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
+               smb_UnixTimeFromDosUTime(&attr.clientModTime, dosTime);
        }
        if ((newScp->unixModeBits & 0222) && (attribute & 1) != 0) {
                /* we're told to make a writable file read-only */
-                attr.unixModeBits = newScp->unixModeBits & ~0222;
-                attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
-        }
+               attr.unixModeBits = newScp->unixModeBits & ~0222;
+               attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
+       }
        else if ((newScp->unixModeBits & 0222) == 0 && (attribute & 1) == 0) {
                /* we're told to make a read-only file writable */
-                attr.unixModeBits = newScp->unixModeBits | 0222;
-                attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
-        }
-        lock_ReleaseMutex(&newScp->mx);
+               attr.unixModeBits = newScp->unixModeBits | 0222;
+               attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
+       }
+       lock_ReleaseMutex(&newScp->mx);
 
        /* now call setattr */
        if (attr.mask)
-               code = cm_SetAttr(newScp, &attr, userp, &req);
+               code = cm_SetAttr(newScp, &attr, userp, &req);
        else
                code = 0;
         
-        cm_ReleaseSCache(newScp);
+       cm_ReleaseSCache(newScp);
        cm_ReleaseUser(userp);
 
-        return code;
+       return code;
 }
 
 long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-        long code;
-        cm_scache_t *rootScp;
+       long code = 0;
+       cm_scache_t *rootScp;
        cm_scache_t *newScp, *dscp;
-        long dosTime;
-        int attrs;
-        cm_user_t *userp;
-        int caseFold;
+       long dosTime;
+       int attrs;
+       cm_user_t *userp;
+       int caseFold;
        char *tidPathp;
        cm_space_t *spacep;
        char *lastComp;
@@ -2865,25 +3818,25 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 
        cm_InitReq(&req);
 
-        pathp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(pathp, NULL);
+       pathp = smb_GetSMBData(inp, NULL);
+       pathp = smb_ParseASCIIBlock(pathp, NULL);
         
-        if (!pathp) {
+       if (!pathp) {
                return CM_ERROR_BADSMB;
        }
         
        if (*pathp == 0)                /* null path */
                pathp = "\\";
 
-       osi_Log1(afsd_logp, "SMB receive getfile attributes path %s",
-                       osi_LogSaveString(afsd_logp, pathp));
+       osi_Log1(smb_logp, "SMB receive getfile attributes path %s",
+                        osi_LogSaveString(smb_logp, pathp));
 
-        rootScp = cm_rootSCachep;
+       rootScp = cm_rootSCachep;
         
        userp = smb_GetUser(vcp, inp);
 
        /* we shouldn't need this for V3 requests, but we seem to */
-               caseFold = CM_FLAG_CASEFOLD;
+       caseFold = CM_FLAG_CASEFOLD;
 
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
 
@@ -2900,13 +3853,16 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         * to explicitly ignore the requests for mount points that haven't
         * yet been evaluated and for directories that haven't yet been
         * fetched.
+        *
+        * We should modify this hack to provide a fake desktop.ini file
+        * http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/shell_basics/shell_basics_extending/custom.asp
         */
        spacep = inp->spacep;
        smb_StripLastComponent(spacep->data, &lastComp, pathp);
-       if (strcmp(lastComp, "\\desktop.ini") == 0) {
+       if (lastComp && stricmp(lastComp, "\\desktop.ini") == 0) {
                code = cm_NameI(rootScp, spacep->data,
-                       caseFold | CM_FLAG_DIRSEARCH | CM_FLAG_FOLLOW,
-                       userp, tidPathp, &req, &dscp);
+                                               caseFold | CM_FLAG_DIRSEARCH | CM_FLAG_FOLLOW,
+                                               userp, tidPathp, &req, &dscp);
                if (code == 0) {
                        if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT
                            && !dscp->mountRootFidp)
@@ -2926,67 +3882,75 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
                }
        }
 
-        code = cm_NameI(rootScp, pathp, caseFold | CM_FLAG_FOLLOW, userp,
-                       tidPathp, &req, &newScp);
+       code = cm_NameI(rootScp, pathp, caseFold | CM_FLAG_FOLLOW, userp,
+                                       tidPathp, &req, &newScp);
 
-        if (code) {
-                cm_ReleaseUser(userp);
-                return code;
-        }
+       if (code) {
+               cm_ReleaseUser(userp);
+               return code;
+       }
         
        /* now lock the vnode with a callback; returns with newScp locked */
        lock_ObtainMutex(&newScp->mx);
-        code = cm_SyncOp(newScp, NULL, userp, &req, 0,
-               CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
-        if (code) {
+       code = cm_SyncOp(newScp, NULL, userp, &req, 0,
+                                        CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
+       if (code) {
                lock_ReleaseMutex(&newScp->mx);
-                cm_ReleaseSCache(newScp);
-                cm_ReleaseUser(userp);
-                return code;
-        }
+               cm_ReleaseSCache(newScp);
+               cm_ReleaseUser(userp);
+               return code;
+       }
 
+#ifdef undef
+    /* use smb_Attributes instead.   Also the fact that a file is 
+        * in a readonly volume doesn't mean it shojuld be marked as RO 
+        */
        if (newScp->fileType == CM_SCACHETYPE_DIRECTORY
-               || newScp->fileType == CM_SCACHETYPE_MOUNTPOINT)
-                       attrs = 0x10;
+               || newScp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+               attrs = SMB_ATTR_DIRECTORY;
        else
-               attrs = 0;
+               attrs = 0;
        if ((newScp->unixModeBits & 0222) == 0 || (newScp->flags & CM_SCACHEFLAG_RO))
-               attrs |= 1;     /* turn on read-only flag */
-        smb_SetSMBParm(outp, 0, attrs);
-        
-        smb_DosUTimeFromUnixTime(&dosTime, newScp->clientModTime);
-        smb_SetSMBParm(outp, 1, dosTime & 0xffff);
-        smb_SetSMBParm(outp, 2, (dosTime>>16) & 0xffff);
-        smb_SetSMBParm(outp, 3, newScp->length.LowPart & 0xffff);
-        smb_SetSMBParm(outp, 4, (newScp->length.LowPart >> 16) & 0xffff);
-        smb_SetSMBParm(outp, 5, 0);
-        smb_SetSMBParm(outp, 6, 0);
-        smb_SetSMBParm(outp, 7, 0);
-        smb_SetSMBParm(outp, 8, 0);
-        smb_SetSMBParm(outp, 9, 0);
-        smb_SetSMBDataLength(outp, 0);
-        lock_ReleaseMutex(&newScp->mx);
-        
-        cm_ReleaseSCache(newScp);
-        cm_ReleaseUser(userp);
+               attrs |= SMB_ATTR_READONLY;     /* turn on read-only flag */
+#else
+    attrs = smb_Attributes(newScp);
+#endif
+
+       smb_SetSMBParm(outp, 0, attrs);
+        
+       smb_DosUTimeFromUnixTime(&dosTime, newScp->clientModTime);
+       smb_SetSMBParm(outp, 1, dosTime & 0xffff);
+       smb_SetSMBParm(outp, 2, (dosTime>>16) & 0xffff);
+       smb_SetSMBParm(outp, 3, newScp->length.LowPart & 0xffff);
+       smb_SetSMBParm(outp, 4, (newScp->length.LowPart >> 16) & 0xffff);
+       smb_SetSMBParm(outp, 5, 0);
+       smb_SetSMBParm(outp, 6, 0);
+       smb_SetSMBParm(outp, 7, 0);
+       smb_SetSMBParm(outp, 8, 0);
+       smb_SetSMBParm(outp, 9, 0);
+       smb_SetSMBDataLength(outp, 0);
+       lock_ReleaseMutex(&newScp->mx);
+
+       cm_ReleaseSCache(newScp);
+       cm_ReleaseUser(userp);
         
-        return 0;
-}
+       return 0;
+}      
 
 long smb_ReceiveCoreTreeDisconnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-        smb_tid_t *tidp;
+       smb_tid_t *tidp;
         
-       osi_Log0(afsd_logp, "SMB receive tree disconnect");
+       osi_Log0(smb_logp, "SMB receive tree disconnect");
 
        /* find the tree and free it */
-        tidp = smb_FindTID(vcp, ((smb_t *)inp)->tid, 0);
-        if (tidp) {
+       tidp = smb_FindTID(vcp, ((smb_t *)inp)->tid, 0);
+       if (tidp) {
                lock_ObtainMutex(&tidp->mx);
                tidp->flags |= SMB_TIDFLAG_DELETE;
-                lock_ReleaseMutex(&tidp->mx);
+               lock_ReleaseMutex(&tidp->mx);
                smb_ReleaseTID(tidp);
-        }
+       }
 
        return 0;
 }
@@ -2994,64 +3958,74 @@ long smb_ReceiveCoreTreeDisconnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_
 long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        smb_fid_t *fidp;
-        char *pathp;
+    char *pathp;
        char *lastNamep;
-        int share;
-        int attribute;
-       long code;
-        cm_user_t *userp;
-        cm_scache_t *scp;
-        long dosTime;
-        int caseFold;
+    int share;
+    int attribute;
+       long code = 0;
+    cm_user_t *userp;
+    cm_scache_t *scp;
+    long dosTime;
+    int caseFold;
        cm_space_t *spacep;
        char *tidPathp;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-       osi_Log0(afsd_logp, "SMB receive open");
-
-        pathp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(pathp, NULL);
+    pathp = smb_GetSMBData(inp, NULL);
+    pathp = smb_ParseASCIIBlock(pathp, NULL);
        
+    osi_Log1(smb_logp, "SMB receive open file [%s]", osi_LogSaveString(smb_logp, pathp));
+
+#ifdef DEBUG_VERBOSE
+    {
+        char *hexpath;
+
+        hexpath = osi_HexifyString( pathp );
+        DEBUG_EVENT2("AFS", "CoreOpen H[%s] A[%s]", hexpath, pathp);
+        free(hexpath);
+    }
+#endif
+
        share = smb_GetSMBParm(inp, 0);
-        attribute = smb_GetSMBParm(inp, 1);
+    attribute = smb_GetSMBParm(inp, 1);
 
        spacep = inp->spacep;
        smb_StripLastComponent(spacep->data, &lastNamep, pathp);
        if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
                /* special case magic file name for receiving IOCTL requests
-                 * (since IOCTL calls themselves aren't getting through).
-                 */
-               fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
+         * (since IOCTL calls themselves aren't getting through).
+         */
+        fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
                smb_SetupIoctlFid(fidp, spacep);
                smb_SetSMBParm(outp, 0, fidp->fid);
-               smb_SetSMBParm(outp, 1, 0);     /* attrs */
-               smb_SetSMBParm(outp, 2, 0);     /* next 2 are DOS time */
-               smb_SetSMBParm(outp, 3, 0);
-               smb_SetSMBParm(outp, 4, 0);     /* next 2 are length */
-               smb_SetSMBParm(outp, 5, 0x7fff);
+        smb_SetSMBParm(outp, 1, 0);    /* attrs */
+        smb_SetSMBParm(outp, 2, 0);    /* next 2 are DOS time */
+        smb_SetSMBParm(outp, 3, 0);
+        smb_SetSMBParm(outp, 4, 0);    /* next 2 are length */
+        smb_SetSMBParm(outp, 5, 0x7fff);
                /* pass the open mode back */
-               smb_SetSMBParm(outp, 6, (share & 0xf));
-               smb_SetSMBDataLength(outp, 0);
-                smb_ReleaseFID(fidp);
-                return 0;
-        }
+        smb_SetSMBParm(outp, 6, (share & 0xf));
+        smb_SetSMBDataLength(outp, 0);
+        smb_ReleaseFID(fidp);
+        return 0;
+    }
 
        userp = smb_GetUser(vcp, inp);
 
        caseFold = CM_FLAG_CASEFOLD;
 
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
-        code = cm_NameI(cm_rootSCachep, pathp, caseFold | CM_FLAG_FOLLOW, userp,
-                       tidPathp, &req, &scp);
+    code = cm_NameI(cm_rootSCachep, pathp, caseFold | CM_FLAG_FOLLOW, userp,
+                    tidPathp, &req, &scp);
         
-        if (code) {
-                cm_ReleaseUser(userp);
+    if (code) {
+        cm_ReleaseUser(userp);
                return code;
        }
         
-               code = cm_CheckOpen(scp, share & 0x7, 0, userp, &req);
+    code = cm_CheckOpen(scp, share & 0x7, 0, userp, &req);
        if (code) {
                cm_ReleaseSCache(scp);
                cm_ReleaseUser(userp);
@@ -3061,47 +4035,47 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        /* don't need callback to check file type, since file types never
         * change, and namei and cm_Lookup all stat the object at least once on
         * a successful return.
-         */
-        if (scp->fileType != CM_SCACHETYPE_FILE) {
+     */
+    if (scp->fileType != CM_SCACHETYPE_FILE) {
                cm_ReleaseSCache(scp);
-                cm_ReleaseUser(userp);
-                return CM_ERROR_ISDIR;
-        }
+        cm_ReleaseUser(userp);
+        return CM_ERROR_ISDIR;
+    }
 
-        fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
-        osi_assert(fidp);
+    fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
+    osi_assert(fidp);
 
        /* save a pointer to the vnode */
-        fidp->scp = scp;
-        
-        if ((share & 0xf) == 0)
-               fidp->flags |= SMB_FID_OPENREAD;
+    fidp->scp = scp;
+
+    if ((share & 0xf) == 0)
+        fidp->flags |= SMB_FID_OPENREAD;
        else if ((share & 0xf) == 1)
-               fidp->flags |= SMB_FID_OPENWRITE;
-       else fidp->flags |= (SMB_FID_OPENREAD | SMB_FID_OPENWRITE);
+        fidp->flags |= SMB_FID_OPENWRITE;
+       else 
+        fidp->flags |= (SMB_FID_OPENREAD | SMB_FID_OPENWRITE);
 
        lock_ObtainMutex(&scp->mx);
        smb_SetSMBParm(outp, 0, fidp->fid);
-        smb_SetSMBParm(outp, 1, smb_Attributes(scp));
+    smb_SetSMBParm(outp, 1, smb_Attributes(scp));
        smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
-        smb_SetSMBParm(outp, 2, dosTime & 0xffff);
-        smb_SetSMBParm(outp, 3, (dosTime >> 16) & 0xffff);
-        smb_SetSMBParm(outp, 4, scp->length.LowPart & 0xffff);
-        smb_SetSMBParm(outp, 5, (scp->length.LowPart >> 16) & 0xffff);
+    smb_SetSMBParm(outp, 2, dosTime & 0xffff);
+    smb_SetSMBParm(outp, 3, (dosTime >> 16) & 0xffff);
+    smb_SetSMBParm(outp, 4, scp->length.LowPart & 0xffff);
+    smb_SetSMBParm(outp, 5, (scp->length.LowPart >> 16) & 0xffff);
        /* pass the open mode back; XXXX add access checks */
-        smb_SetSMBParm(outp, 6, (share & 0xf));
-        smb_SetSMBDataLength(outp, 0);
+    smb_SetSMBParm(outp, 6, (share & 0xf));
+    smb_SetSMBDataLength(outp, 0);
        lock_ReleaseMutex(&scp->mx);
         
        /* notify open */
-        cm_Open(scp, 0, userp);
+    cm_Open(scp, 0, userp);
 
        /* send and free packet */
-        smb_ReleaseFID(fidp);
-        cm_ReleaseUser(userp);
-        /* don't release scp, since we've squirreled away the pointer in the fid struct */
-
-        return 0;
+    smb_ReleaseFID(fidp);
+    cm_ReleaseUser(userp);
+    /* don't release scp, since we've squirreled away the pointer in the fid struct */
+    return 0;
 }
 
 typedef struct smb_unlinkRock {
@@ -3110,79 +4084,83 @@ typedef struct smb_unlinkRock {
        cm_req_t *reqp;
        smb_vc_t *vcp;
        char *maskp;            /* pointer to the star pattern */
-       int hasTilde;
+       int flags;
        int any;
 } smb_unlinkRock_t;
 
-long smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
+int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
 {
-       long code;
-        smb_unlinkRock_t *rockp;
-        int caseFold;
+       long code = 0;
+       smb_unlinkRock_t *rockp;
+       int caseFold;
        int match;
        char shortName[13];
        char *matchName;
         
-        rockp = vrockp;
+       rockp = vrockp;
 
-       if (rockp->vcp->flags & SMB_VCFLAG_USEV3)
-               caseFold = CM_FLAG_CASEFOLD;
-       else 
-               caseFold = CM_FLAG_CASEFOLD | CM_FLAG_8DOT3;
+    caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
+    if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
+        caseFold |= CM_FLAG_8DOT3;
 
        matchName = dep->name;
        match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
        if (!match
-           && rockp->hasTilde
+           && (rockp->flags & SMB_MASKFLAG_TILDE)
            && !cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
                matchName = shortName;
-               match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
+        /* 8.3 matches are always case insensitive */
+        match = smb_V3MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
        }
        if (match) {
                osi_Log1(smb_logp, "Unlinking %s",
-                               osi_LogSaveString(smb_logp, matchName));
-               code = cm_Unlink(dscp, dep->name, rockp->userp, rockp->reqp);
+                                osi_LogSaveString(smb_logp, matchName));
+               code = cm_Unlink(dscp, dep->name, rockp->userp, rockp->reqp);
                if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                        smb_NotifyChange(FILE_ACTION_REMOVED,
-                                        FILE_NOTIFY_CHANGE_FILE_NAME,
-                                        dscp, dep->name, NULL, TRUE);
-               if (code == 0)
+                                                        FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                        dscp, dep->name, NULL, TRUE);
+               if (code == 0) {
                        rockp->any = 1;
+            /* If we made a case sensitive exact match, we might as well quit now. */
+            if(!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp))
+                code = CM_ERROR_STOPNOW;
+        }
        }
-        else code = 0;
+       else code = 0;
 
-        return code;
+       return code;
 }
 
 long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        int attribute;
-        long code;
-        char *pathp;
-        char *tp;
-        cm_space_t *spacep;
-        cm_scache_t *dscp;
-        char *lastNamep;
-        smb_unlinkRock_t rock;
-        cm_user_t *userp;
-        osi_hyper_t thyper;
-        int caseFold;
+       long code = 0;
+       char *pathp;
+       char *tp;
+       cm_space_t *spacep;
+       cm_scache_t *dscp;
+       char *lastNamep;
+       smb_unlinkRock_t rock;
+       cm_user_t *userp;
+       osi_hyper_t thyper;
+       int caseFold;
        char *tidPathp;
-        cm_req_t req;
+       cm_req_t req;
 
        cm_InitReq(&req);
 
-        attribute = smb_GetSMBParm(inp, 0);
+       attribute = smb_GetSMBParm(inp, 0);
         
        tp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(tp, &tp);
+       pathp = smb_ParseASCIIBlock(tp, &tp);
 
        osi_Log1(smb_logp, "SMB receive unlink %s",
-                       osi_LogSaveString(smb_logp, pathp));
+                        osi_LogSaveString(smb_logp, pathp));
 
        spacep = inp->spacep;
-        smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+       smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
        userp = smb_GetUser(vcp, inp);
 
@@ -3190,101 +4168,122 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, userp, tidPathp,
-                       &req, &dscp);
+                                       &req, &dscp);
 
-        if (code) {
-                cm_ReleaseUser(userp);
-                return code;
-        }
+       if (code) {
+               cm_ReleaseUser(userp);
+               return code;
+       }
         
-        /* otherwise, scp points to the parent directory.
-         */
-        if (!lastNamep) lastNamep = pathp;
-        else lastNamep++;
+       /* otherwise, scp points to the parent directory. */
+       if (!lastNamep) 
+               lastNamep = pathp;
+       else 
+               lastNamep++;
 
        rock.any = 0;
-        rock.maskp = smb_FindMask(pathp);
-       rock.hasTilde = ((strchr(rock.maskp, '~') != NULL) ? 1 : 0);
+       rock.maskp = smb_FindMask(pathp);
+       rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
         
        thyper.LowPart = 0;
-        thyper.HighPart = 0;
+       thyper.HighPart = 0;
        rock.userp = userp;
        rock.reqp = &req;
-        rock.dscp = dscp;
-        rock.vcp = vcp;
+       rock.dscp = dscp;
+       rock.vcp = vcp;
+
+    /* Now, if we aren't dealing with a wildcard match, we first try an exact 
+     * match.  If that fails, we do a case insensitve match. 
+     */
+    if (!(rock.flags & SMB_MASKFLAG_TILDE) &&
+        !smb_IsStarMask(rock.maskp)) {
         code = cm_ApplyDir(dscp, smb_UnlinkProc, &rock, &thyper, userp, &req, NULL);
+        if(!rock.any) {
+            thyper.LowPart = 0;
+            thyper.HighPart = 0;
+            rock.flags |= SMB_MASKFLAG_CASEFOLD;
+        }
+    }
+    if (!rock.any)
+        code = cm_ApplyDir(dscp, smb_UnlinkProc, &rock, &thyper, userp, &req, NULL);
+    
+    if (code == CM_ERROR_STOPNOW) 
+        code = 0;
 
-        cm_ReleaseUser(userp);
+       cm_ReleaseUser(userp);
         
-        cm_ReleaseSCache(dscp);
+       cm_ReleaseSCache(dscp);
 
-        if (code == 0 && !rock.any)
+       if (code == 0 && !rock.any)
                code = CM_ERROR_NOSUCHFILE;
-        return code;
+       return code;
 }
 
 typedef struct smb_renameRock {
-        cm_scache_t *odscp;    /* old dir */
-        cm_scache_t *ndscp;    /* new dir */
-        cm_user_t *userp;      /* user */
+       cm_scache_t *odscp;     /* old dir */
+       cm_scache_t *ndscp;     /* new dir */
+       cm_user_t *userp;       /* user */
        cm_req_t *reqp;         /* request struct */
-        smb_vc_t *vcp;         /* virtual circuit */
+       smb_vc_t *vcp;          /* virtual circuit */
        char *maskp;            /* pointer to star pattern of old file name */
-       int hasTilde;           /* star pattern might be shortname? */
-        char *newNamep;                /* ptr to the new file's name */
+       int flags;                  /* tilde, casefold, etc */
+       char *newNamep;         /* ptr to the new file's name */
 } smb_renameRock_t;
 
-long smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
+int smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
 {
-       long code;
-        smb_renameRock_t *rockp;
-        int caseFold;
+       long code = 0;
+       smb_renameRock_t *rockp;
+       int caseFold;
        int match;
        char shortName[13];
         
-        rockp = vrockp;
+       rockp = (smb_renameRock_t *) vrockp;
 
-       if (rockp->vcp->flags & SMB_VCFLAG_USEV3)
-               caseFold = CM_FLAG_CASEFOLD;
-       else 
-               caseFold = CM_FLAG_CASEFOLD | CM_FLAG_8DOT3;
+    caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
+    if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
+        caseFold |= CM_FLAG_8DOT3;
 
        match = smb_V3MatchMask(dep->name, rockp->maskp, caseFold);
        if (!match
-           && rockp->hasTilde
+           && (rockp->flags & SMB_MASKFLAG_TILDE)
            && !cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
                match = smb_V3MatchMask(shortName, rockp->maskp, caseFold);
        }
        if (match) {
-               code = cm_Rename(rockp->odscp, dep->name,
-                       rockp->ndscp, rockp->newNamep, rockp->userp,
-                       rockp->reqp);
+               code = cm_Rename(rockp->odscp, dep->name,
+                                                rockp->ndscp, rockp->newNamep, rockp->userp,
+                                                rockp->reqp);  
                /* if the call worked, stop doing the search now, since we
                 * really only want to rename one file.
-                 */
-               if (code == 0) code = CM_ERROR_STOPNOW;
+                */
+               if (code == 0) 
+                       code = CM_ERROR_STOPNOW;
        }
-        else code = 0;
+       else code = 0;
 
-        return code;
+       return code;
 }
 
 long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-        long code;
-        char *oldPathp;
-        char *newPathp;
-        char *tp;
-        cm_space_t *spacep;
-        smb_renameRock_t rock;
-        cm_scache_t *oldDscp;
-        cm_scache_t *newDscp;
-        char *oldLastNamep;
-        char *newLastNamep;
-        osi_hyper_t thyper;
-        cm_user_t *userp;
-        int caseFold;
+       long code = 0;
+       char *oldPathp;
+       char *newPathp;
+       char *tp;
+       cm_space_t *spacep = NULL;
+       smb_renameRock_t rock;
+       cm_scache_t *oldDscp = NULL;
+       cm_scache_t *newDscp = NULL;
+       cm_scache_t *tmpscp= NULL;
+       cm_scache_t *tmpscp2 = NULL;
+       char *oldLastNamep;
+       char *newLastNamep;
+       osi_hyper_t thyper;
+       cm_user_t *userp;
+       int caseFold;
        char *tidPathp;
        DWORD filter;
        cm_req_t req;
@@ -3292,80 +4291,122 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        cm_InitReq(&req);
         
        tp = smb_GetSMBData(inp, NULL);
-        oldPathp = smb_ParseASCIIBlock(tp, &tp);
-        newPathp = smb_ParseASCIIBlock(tp, &tp);
+       oldPathp = smb_ParseASCIIBlock(tp, &tp);
+       newPathp = smb_ParseASCIIBlock(tp, &tp);
 
-       osi_Log2(afsd_logp, "smb rename %s to %s",
-                osi_LogSaveString(afsd_logp, oldPathp),
-                osi_LogSaveString(afsd_logp, newPathp));
+       osi_Log2(smb_logp, "smb rename [%s] to [%s]",
+                        osi_LogSaveString(smb_logp, oldPathp),
+                        osi_LogSaveString(smb_logp, newPathp));
 
        spacep = inp->spacep;
-        smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
+       smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
 
        userp = smb_GetUser(vcp, inp);
 
-/*
- * Changed to use CASEFOLD always.  This enables us to rename Foo/baz when
- * what actually exists is foo/baz.  I don't know why the code used to be
- * the way it was.  1/29/96
- *
- *             caseFold = ((vcp->flags & SMB_VCFLAG_USEV3) ? 0: CM_FLAG_CASEFOLD);
- *
- * Changed to use CM_FLAG_FOLLOW.  7/24/96
- *
- *     caseFold = CM_FLAG_CASEFOLD;
- */
+ /*
+  * Changed to use CASEFOLD always.  This enables us to rename Foo/baz when
+  * what actually exists is foo/baz.  I don't know why the code used to be
+  * the way it was.  1/29/96
+  *
+  *            caseFold = ((vcp->flags & SMB_VCFLAG_USEV3) ? 0: CM_FLAG_CASEFOLD);
+  *
+  * Changed to use CM_FLAG_FOLLOW.  7/24/96
+  *
+  *    caseFold = CM_FLAG_CASEFOLD;
+  */
        caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
 
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
-               userp, tidPathp, &req, &oldDscp);
+                                       userp, tidPathp, &req, &oldDscp);
 
-        if (code) {
-                cm_ReleaseUser(userp);
-                return code;
-        }
+       if (code) {
+               cm_ReleaseUser(userp);
+               return code;
+       }
         
        smb_StripLastComponent(spacep->data, &newLastNamep, newPathp);
        code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
-               userp, tidPathp, &req, &newDscp);
+                                       userp, tidPathp, &req, &newDscp);
 
-        if (code) {
+       if (code) {
                cm_ReleaseSCache(oldDscp);
-                cm_ReleaseUser(userp);
-                return code;
-        }
+               cm_ReleaseUser(userp);
+               return code;
+       }
         
-        /* otherwise, oldDscp and newDscp point to the corresponding directories.
-         * next, get the component names, and lower case them.
-         */
+       /* otherwise, oldDscp and newDscp point to the corresponding directories.
+        * next, get the component names, and lower case them.
+        */
 
-        /* handle the old name first */
-        if (!oldLastNamep) oldLastNamep = oldPathp;
-        else oldLastNamep++;
+       /* handle the old name first */
+       if (!oldLastNamep) 
+               oldLastNamep = oldPathp;
+       else 
+               oldLastNamep++;
 
        /* and handle the new name, too */
-        if (!newLastNamep) newLastNamep = newPathp;
-        else newLastNamep++;
+       if (!newLastNamep) 
+               newLastNamep = newPathp;
+       else 
+               newLastNamep++;
+
+    /* TODO: The old name could be a wildcard.  The new name must not be */
        
        /* do the vnode call */
-        rock.odscp = oldDscp;
-        rock.ndscp = newDscp;
-        rock.userp = userp;
+       rock.odscp = oldDscp;
+       rock.ndscp = newDscp;
+       rock.userp = userp;
        rock.reqp = &req;
-        rock.vcp = vcp;
-        rock.maskp = oldLastNamep;
-       rock.hasTilde = ((strchr(oldLastNamep, '~') != NULL) ? 1 : 0);
-        rock.newNamep = newLastNamep;
-
-       /* now search the dir for the pattern, and do the appropriate rename when
-         * found.
+       rock.vcp = vcp;
+       rock.maskp = oldLastNamep;
+       rock.flags = ((strchr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
+       rock.newNamep = newLastNamep;
+
+    /* Check if the file already exists; if so return error */
+       code = cm_Lookup(newDscp,newLastNamep,CM_FLAG_CHECKPATH,userp,&req,&tmpscp);
+       if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) {
+        osi_Log2(afsd_logp, "  lookup returns %ld for [%s]", code,
+                 osi_LogSaveString(afsd_logp, newLastNamep));
+        /* Check if the old and the new names differ only in case. If so return
+         * success, else return CM_ERROR_EXISTS 
          */
+        if (!code && oldDscp == newDscp && !stricmp(oldLastNamep, newLastNamep)) {
+
+            /* This would be a success only if the old file is *as same as* the new file */
+            code = cm_Lookup(oldDscp, oldLastNamep, CM_FLAG_CHECKPATH, userp, &req, &tmpscp2);
+            if (!code) {
+                if (tmpscp == tmpscp2) 
+                    code = 0;
+                else 
+                    code = CM_ERROR_EXISTS;
+                cm_ReleaseSCache(tmpscp2);
+                               tmpscp2 = NULL;
+            } else {
+                code = CM_ERROR_NOSUCHFILE;
+            }
+        } else {
+            /* file exist, do not rename, also fixes move */
+            osi_Log0(afsd_logp, "Can't rename.  Target already exists");
+            code = CM_ERROR_EXISTS;
+        }
+
+               if(tmpscp != NULL)
+            cm_ReleaseSCache(tmpscp);
+        cm_ReleaseSCache(newDscp);
+        cm_ReleaseSCache(oldDscp);
+        cm_ReleaseUser(userp);
+           return code; 
+       }
+
+    /* Now search the directory for the pattern, and do the appropriate rename when found */
        thyper.LowPart = 0;             /* search dir from here */
-        thyper.HighPart = 0;
-        code = cm_ApplyDir(oldDscp, smb_RenameProc, &rock, &thyper, userp, &req, NULL);
+    thyper.HighPart = 0;
 
-        if (code == CM_ERROR_STOPNOW)
+    code = cm_ApplyDir(oldDscp, smb_RenameProc, &rock, &thyper, userp, &req, NULL);
+
+    if (code == CM_ERROR_STOPNOW)
                code = 0;
        else if (code == 0)
                code = CM_ERROR_NOSUCHFILE;
@@ -3379,25 +4420,25 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        if (oldDscp == newDscp) {
                if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
                        smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME,
-                                        filter, oldDscp, oldLastNamep,
-                                        newLastNamep, TRUE);
+                                                        filter, oldDscp, oldLastNamep,
+                                                        newLastNamep, TRUE);
        } else {
                if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
                        smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME,
-                                        filter, oldDscp, oldLastNamep,
-                                        NULL, TRUE);
+                                                        filter, oldDscp, oldLastNamep,
+                                                        NULL, TRUE);
                if (newDscp->flags & CM_SCACHEFLAG_ANYWATCH)
                        smb_NotifyChange(FILE_ACTION_RENAMED_NEW_NAME,
-                                        filter, newDscp, newLastNamep,
-                                        NULL, TRUE);
+                                                        filter, newDscp, newLastNamep,
+                                                        NULL, TRUE);
        }
 
-       cm_ReleaseUser(userp);
-        
-        cm_ReleaseSCache(oldDscp);
-        cm_ReleaseSCache(newDscp);
-        
-        return code;
+    if(tmpscp != NULL) 
+        cm_ReleaseSCache(tmpscp);
+    cm_ReleaseUser(userp);
+       cm_ReleaseSCache(oldDscp);
+       cm_ReleaseSCache(newDscp);
+       return code;
 }
 
 typedef struct smb_rmdirRock {
@@ -3405,24 +4446,27 @@ typedef struct smb_rmdirRock {
        cm_user_t *userp;
        cm_req_t *reqp;
        char *maskp;            /* pointer to the star pattern */
-       int hasTilde;
+       int flags;
        int any;
 } smb_rmdirRock_t;
 
-long smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
+int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
 {
-       long code;
-        smb_rmdirRock_t *rockp;
+       long code = 0;
+       smb_rmdirRock_t *rockp;
        int match;
        char shortName[13];
        char *matchName;
         
-        rockp = vrockp;
+       rockp = (smb_rmdirRock_t *) vrockp;
 
        matchName = dep->name;
-       match = (cm_stricmp(matchName, rockp->maskp) == 0);
+    if (rockp->flags & SMB_MASKFLAG_CASEFOLD)
+        match = (cm_stricmp(matchName, rockp->maskp) == 0);
+    else
+        match = (strcmp(matchName, rockp->maskp) == 0);
        if (!match
-           && rockp->hasTilde
+           && (rockp->flags & SMB_MASKFLAG_TILDE)
            && !cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
                matchName = shortName;
@@ -3430,113 +4474,125 @@ long smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
        }
        if (match) {
                osi_Log1(smb_logp, "Removing directory %s",
-                               osi_LogSaveString(smb_logp, matchName));
-               code = cm_RemoveDir(dscp, dep->name, rockp->userp, rockp->reqp);
+                                osi_LogSaveString(smb_logp, matchName));
+               code = cm_RemoveDir(dscp, dep->name, rockp->userp, rockp->reqp);
                if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                        smb_NotifyChange(FILE_ACTION_REMOVED,
-                                        FILE_NOTIFY_CHANGE_DIR_NAME,
-                                        dscp, dep->name, NULL, TRUE);
+                                                        FILE_NOTIFY_CHANGE_DIR_NAME,
+                                                        dscp, dep->name, NULL, TRUE);
                if (code == 0)
                        rockp->any = 1;
        }
-        else code = 0;
+       else code = 0;
 
-        return code;
+       return code;
 }
 
 long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-        long code;
-        char *pathp;
-        char *tp;
-        cm_space_t *spacep;
-        cm_scache_t *dscp;
-        char *lastNamep;
+       long code = 0;
+       char *pathp;
+       char *tp;
+       cm_space_t *spacep;
+       cm_scache_t *dscp;
+       char *lastNamep;
        smb_rmdirRock_t rock;
-        cm_user_t *userp;
+       cm_user_t *userp;
        osi_hyper_t thyper;
-        int caseFold;
+       int caseFold;
        char *tidPathp;
-        cm_req_t req;
+       cm_req_t req;
 
        cm_InitReq(&req);
 
        tp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(tp, &tp);
+       pathp = smb_ParseASCIIBlock(tp, &tp);
 
        spacep = inp->spacep;
-        smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+       smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
        userp = smb_GetUser(vcp, inp);
 
-               caseFold = CM_FLAG_CASEFOLD;
+       caseFold = CM_FLAG_CASEFOLD;
 
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
-               userp, tidPathp, &req, &dscp);
+                                       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. */
-        if (!lastNamep) lastNamep = pathp;
-        else lastNamep++;
+       /* otherwise, scp points to the parent directory. */
+       if (!lastNamep) 
+               lastNamep = pathp;
+       else 
+               lastNamep++;
        
        rock.any = 0;
        rock.maskp = lastNamep;
-       rock.hasTilde = ((strchr(rock.maskp, '~') != NULL) ? 1 : 0);
+       rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
 
        thyper.LowPart = 0;
        thyper.HighPart = 0;
        rock.userp = userp;
        rock.reqp = &req;
        rock.dscp = dscp;
-       code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+    /* First do a case sensitive match, and if that fails, do a case insensitive match */
+    code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+    if (code == 0 && !rock.any) {
+        thyper.LowPart = 0;
+        thyper.HighPart = 0;
+        rock.flags |= SMB_MASKFLAG_CASEFOLD;
+        code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+    }
 
-        cm_ReleaseUser(userp);
+       cm_ReleaseUser(userp);
         
-        cm_ReleaseSCache(dscp);
+       cm_ReleaseSCache(dscp);
 
        if (code == 0 && !rock.any)
                code = CM_ERROR_NOSUCHFILE;        
-        return code;
+       return code;
 }
 
 long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        unsigned short fid;
-        smb_fid_t *fidp;
-        cm_user_t *userp;
-        long code;
-        cm_req_t req;
+    smb_fid_t *fidp;
+    cm_user_t *userp;
+    long code = 0;
+    cm_req_t req;
 
        cm_InitReq(&req);
 
        fid = smb_GetSMBParm(inp, 0);
         
-       osi_Log1(afsd_logp, "SMB flush fid %d", fid);
+       osi_Log1(smb_logp, "SMB flush fid %d", fid);
 
        fid = smb_ChainFID(fid, inp);
-        fidp = smb_FindFID(vcp, fid, 0);
-        if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
-                return CM_ERROR_BADFD;
-        }
-        
-        userp = smb_GetUser(vcp, inp);
-
-        lock_ObtainMutex(&fidp->mx);
-        if (fidp->flags & SMB_FID_OPENWRITE)
-               code = cm_FSync(fidp->scp, userp, &req);
-       else code = 0;
-        lock_ReleaseMutex(&fidp->mx);
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+        if (fidp)
+            smb_ReleaseFID(fidp);
+        return CM_ERROR_BADFD;
+    }
+        
+    userp = smb_GetUser(vcp, inp);
+
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->flags & SMB_FID_OPENWRITE)
+        code = cm_FSync(fidp->scp, userp, &req);
+       else 
+               code = 0;
+    lock_ReleaseMutex(&fidp->mx);
         
-        smb_ReleaseFID(fidp);
+    smb_ReleaseFID(fidp);
         
-        cm_ReleaseUser(userp);
+    cm_ReleaseUser(userp);
         
-        return code;
+    return code;
 }
 
 struct smb_FullNameRock {
@@ -3545,23 +4601,23 @@ struct smb_FullNameRock {
        char *fullName;
 };
 
-long smb_FullNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
+int smb_FullNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
        osi_hyper_t *offp)
 {
        char shortName[13];
        struct smb_FullNameRock *vrockp;
 
-       vrockp = rockp;
+       vrockp = (struct smb_FullNameRock *)rockp;
 
        if (!cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
 
-               if (strcmp(shortName, vrockp->name) == 0) {
+               if (cm_stricmp(shortName, vrockp->name) == 0) {
                        vrockp->fullName = strdup(dep->name);
                        return CM_ERROR_STOPNOW;
                }
        }
-       if (stricmp(dep->name, vrockp->name) == 0
+       if (cm_stricmp(dep->name, vrockp->name) == 0
            && ntohl(dep->fid.vnode) == vrockp->vnode->fid.vnode
            && ntohl(dep->fid.unique) == vrockp->vnode->fid.unique) {
                vrockp->fullName = strdup(dep->name);
@@ -3574,7 +4630,7 @@ void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, char *pathp,
        char **newPathp, cm_user_t *userp, cm_req_t *reqp)
 {
        struct smb_FullNameRock rock;
-       long code;
+       long code = 0;
 
        rock.name = pathp;
        rock.vnode = scp;
@@ -3590,10 +4646,10 @@ void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, char *pathp,
 long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        unsigned short fid;
-        smb_fid_t *fidp;
-        cm_user_t *userp;
+    smb_fid_t *fidp;
+    cm_user_t *userp;
        long dosTime;
-        long code;
+    long code = 0;
        cm_req_t req;
 
        cm_InitReq(&req);
@@ -3601,41 +4657,41 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        fid = smb_GetSMBParm(inp, 0);
        dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
         
-       osi_Log1(afsd_logp, "SMB close fid %d", fid);
+       osi_Log1(smb_logp, "SMB close fid %d", fid);
 
        fid = smb_ChainFID(fid, inp);
-        fidp = smb_FindFID(vcp, fid, 0);
-        if (!fidp) {
-                return CM_ERROR_BADFD;
-        }
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp) {
+        return CM_ERROR_BADFD;
+    }
         
        userp = smb_GetUser(vcp, inp);
 
-        lock_ObtainMutex(&fidp->mx);
+    lock_ObtainMutex(&fidp->mx);
 
        /* Don't jump the gun on an async raw write */
        while (fidp->raw_writers) {
                lock_ReleaseMutex(&fidp->mx);
-               WaitForSingleObject(fidp->raw_write_event, RAWTIMEOUT);
+               thrd_WaitForSingleObject_Event(fidp->raw_write_event, RAWTIMEOUT);
                lock_ObtainMutex(&fidp->mx);
        }
 
        fidp->flags |= SMB_FID_DELETE;
         
        /* watch for ioctl closes, and read-only opens */
-        if (fidp->scp != NULL
-           && (fidp->flags & (SMB_FID_OPENWRITE | SMB_FID_DELONCLOSE))
-                 == SMB_FID_OPENWRITE) {
+    if (fidp->scp != NULL
+        && (fidp->flags & (SMB_FID_OPENWRITE | SMB_FID_DELONCLOSE))
+         == SMB_FID_OPENWRITE) {
                if (dosTime != 0 && dosTime != -1) {
                        fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
-                        /* This fixes defect 10958 */
-                        CompensateForSmbClientLastWriteTimeBugs(&dosTime);
-                       smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime,
-                                                dosTime);
+            /* This fixes defect 10958 */
+            CompensateForSmbClientLastWriteTimeBugs(&dosTime);
+                       smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
                }
-               code = cm_FSync(fidp->scp, userp, &req);
+        code = cm_FSync(fidp->scp, userp, &req);
        }
-       else code = 0;
+       else 
+        code = 0;
 
        if (fidp->flags & SMB_FID_DELONCLOSE) {
                cm_scache_t *dscp = fidp->NTopen_dscp;
@@ -3647,41 +4703,46 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                        code = cm_RemoveDir(dscp, fullPathp, userp, &req);
                        if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                                smb_NotifyChange(FILE_ACTION_REMOVED,
-                                                FILE_NOTIFY_CHANGE_DIR_NAME,
-                                                dscp, fullPathp, NULL, TRUE);
+                                 FILE_NOTIFY_CHANGE_DIR_NAME,
+                                 dscp, fullPathp, NULL, TRUE);
                }
-               else {
+               else 
+        {
                        code = cm_Unlink(dscp, fullPathp, userp, &req);
                        if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                                smb_NotifyChange(FILE_ACTION_REMOVED,
-                                                FILE_NOTIFY_CHANGE_FILE_NAME,
-                                                dscp, fullPathp, NULL, TRUE);
+                                 FILE_NOTIFY_CHANGE_FILE_NAME,
+                                 dscp, fullPathp, NULL, TRUE);
                }
                free(fullPathp);
        }
-        lock_ReleaseMutex(&fidp->mx);
+    lock_ReleaseMutex(&fidp->mx);
 
-        if (fidp->flags & SMB_FID_NTOPEN) {
+    if (fidp->flags & SMB_FID_NTOPEN) {
                cm_ReleaseSCache(fidp->NTopen_dscp);
                free(fidp->NTopen_pathp);
        }
        if (fidp->NTopen_wholepathp)
                free(fidp->NTopen_wholepathp);
-        smb_ReleaseFID(fidp);
-        
+    
+    smb_ReleaseFID(fidp);
        cm_ReleaseUser(userp);
-        
-        return code;
+    return code;
 }
 
 /*
  * smb_ReadData -- common code for Read, Read And X, and Raw Read
  */
+#ifndef DJGPP
 long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
        cm_user_t *userp, long *readp)
+#else /* DJGPP */
+long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
+       cm_user_t *userp, long *readp, int dosflag)
+#endif /* !DJGPP */
 {
        osi_hyper_t offset;
-       long code;
+       long code = 0;
        cm_scache_t *scp;
        cm_buf_t *bufferp;
        osi_hyper_t fileLength;
@@ -3714,7 +4775,7 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
        /* start by looking up the file's end */
        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 entry locked, look up the length */
@@ -3740,76 +4801,82 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
        *readp = count;
 
-        /* now, copy the data one buffer at a time,
+       /* now, copy the data one buffer at a time,
         * until we've filled the request packet
         */
-        while (1) {
+       while (1) {
                /* if we've copied all the data requested, we're done */
-                if (count <= 0) break;
+               if (count <= 0) break;
                 
-                /* otherwise, load up a buffer of data */
-                thyper.HighPart = offset.HighPart;
-                thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1);
-                if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
+               /* otherwise, load up a buffer of data */
+               thyper.HighPart = offset.HighPart;
+               thyper.LowPart = offset.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);
 
-                        lock_ObtainMutex(&scp->mx);
-                        if (code) goto done;
-                        bufferOffset = thyper;
+                       lock_ObtainMutex(&scp->mx);
+                       if (code) goto done;
+                       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, 0,
-                                       CM_SCACHESYNC_NEEDCALLBACK
-                                       | CM_SCACHESYNC_READ);
+                                                                 CM_SCACHESYNC_NEEDCALLBACK
+                                                                 | CM_SCACHESYNC_READ);
                                if (code) goto done;
                                 
-                                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) {
+                               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;
+                               bufferp = NULL;
                                goto done;
                        }
-                }      /* if (wrong buffer) ... */
+               }       /* if (wrong buffer) ... */
                 
-                /* now we have the right buffer loaded.  Copy out the
-                 * data from here to the user's buffer.
-                 */
+               /* now we have the right buffer loaded.  Copy out the
+                * data from here to the user's buffer.
+                */
                bufIndex = offset.LowPart & (buf_bufferSize - 1);
 
                /* and figure out how many bytes we want from this buffer */
-                nbytes = buf_bufferSize - bufIndex;    /* what remains in buffer */
-                if (nbytes > count) nbytes = count;    /* don't go past EOF */
+               nbytes = buf_bufferSize - bufIndex;     /* what remains in buffer */
+               if (nbytes > count) nbytes = count;     /* don't go past EOF */
                
-                /* now copy the data */
-                memcpy(op, bufferp->datap + bufIndex, nbytes);
+               /* now copy the data */
+#ifdef DJGPP
+               if (dosflag)
+                       dosmemput(bufferp->datap + bufIndex, nbytes, (dos_ptr)op);
+               else
+#endif /* DJGPP */
+                       memcpy(op, bufferp->datap + bufIndex, nbytes);
                 
                /* adjust counters, pointers, etc. */
-                op += nbytes;
-                count -= nbytes;
-                thyper.LowPart = nbytes;
-                thyper.HighPart = 0;
-                offset = LargeIntegerAdd(thyper, offset);
-        } /* while 1 */
-
-done:
+               op += nbytes;
+               count -= nbytes;
+               thyper.LowPart = nbytes;
+               thyper.HighPart = 0;
+               offset = LargeIntegerAdd(thyper, offset);
+       } /* while 1 */
+
+  done:
        lock_ReleaseMutex(&scp->mx);
        lock_ReleaseMutex(&fidp->mx);
-       if (bufferp) buf_Release(bufferp);
+       if (bufferp) 
+               buf_Release(bufferp);
 
        if (code == 0 && sequential)
                cm_ConsiderPrefetch(scp, &lastByte, userp, &req);
@@ -3820,30 +4887,35 @@ done:
 /*
  * smb_WriteData -- common code for Write and Raw Write
  */
+#ifndef DJGPP
 long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
        cm_user_t *userp, long *writtenp)
+#else /* DJGPP */
+long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
+       cm_user_t *userp, long *writtenp, int dosflag)
+#endif /* !DJGPP */
 {
        osi_hyper_t offset;
-        long code;
+       long code = 0;
        long written = 0;
        cm_scache_t *scp;
-        osi_hyper_t fileLength;        /* file's length at start of write */
+       osi_hyper_t fileLength; /* file's length at start of write */
        osi_hyper_t minLength;  /* don't read past this */
        long nbytes;            /* # of bytes to transfer this iteration */
-        cm_buf_t *bufferp;
-        osi_hyper_t thyper;            /* hyper tmp variable */
-        osi_hyper_t bufferOffset;
-        long bufIndex;                 /* index in buffer where our data is */
-        int doWriteBack;
-        osi_hyper_t writeBackOffset;   /* offset of region to write back when
-                                        * I/O is done */
+       cm_buf_t *bufferp;
+       osi_hyper_t thyper;             /* hyper tmp variable */
+       osi_hyper_t bufferOffset;
+       long bufIndex;                  /* index in buffer where our data is */
+       int doWriteBack;
+       osi_hyper_t writeBackOffset;    /* offset of region to write back when
+       * I/O is done */
        DWORD filter = 0;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-        bufferp = NULL;
-        doWriteBack = 0;
+       bufferp = NULL;
+       doWriteBack = 0;
        offset = *offsetp;
 
        lock_ObtainMutex(&fidp->mx);
@@ -3851,19 +4923,20 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
        lock_ObtainMutex(&scp->mx);
 
        /* start by looking up the file's end */
-        code = cm_SyncOp(scp, NULL, userp, &req, 0,
-               CM_SCACHESYNC_NEEDCALLBACK
-                | CM_SCACHESYNC_SETSTATUS
-                | CM_SCACHESYNC_GETSTATUS);
-       if (code) goto done;
+       code = cm_SyncOp(scp, NULL, userp, &req, 0,
+                                        CM_SCACHESYNC_NEEDCALLBACK
+                                        | CM_SCACHESYNC_SETSTATUS
+                                        | CM_SCACHESYNC_GETSTATUS);
+       if (code) 
+               goto done;
         
        /* make sure we have a writable FD */
-        if (!(fidp->flags & SMB_FID_OPENWRITE)) {
+       if (!(fidp->flags & SMB_FID_OPENWRITE)) {
                code = CM_ERROR_BADFDOP;
                goto done;
-        }
+       }
        
-        /* now we have the entry locked, look up the length */
+       /* now we have the entry locked, look up the length */
        fileLength = scp->length;
        minLength = fileLength;
        if (LargeIntegerGreaterThan(minLength, scp->serverLength))
@@ -3871,87 +4944,86 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
        /* adjust file length if we extend past EOF */
        thyper.LowPart = count;
-        thyper.HighPart = 0;
+       thyper.HighPart = 0;
        thyper = LargeIntegerAdd(offset, thyper);       /* where write should end */
        if (LargeIntegerGreaterThan(thyper, fileLength)) {
                /* we'd write past EOF, so extend the file */
                scp->mask |= CM_SCACHEMASK_LENGTH;
-                scp->length = thyper;
-               filter |=
-                   (FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE);
-        } else
+               scp->length = thyper;
+               filter |= (FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE);
+       } else
                filter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
         
-        /* now, if the new position (thyper) and the old (offset) are in
+       /* now, if the new position (thyper) and the old (offset) are in
         * different storeback windows, remember to store back the previous
         * storeback window when we're done with the write.
-         */
+        */
        if ((thyper.LowPart & (-cm_chunkSize)) !=
-               (offset.LowPart & (-cm_chunkSize))) {
+                (offset.LowPart & (-cm_chunkSize))) {
                /* they're different */
-                doWriteBack = 1;
-                writeBackOffset.HighPart = offset.HighPart;
-                writeBackOffset.LowPart = offset.LowPart & (-cm_chunkSize);
-        }
+               doWriteBack = 1;
+               writeBackOffset.HighPart = offset.HighPart;
+               writeBackOffset.LowPart = offset.LowPart & (-cm_chunkSize);
+       }
         
-        *writtenp = count;
+       *writtenp = count;
 
-        /* now, copy the data one buffer at a time, until we've filled the
+       /* now, copy the data one buffer at a time, until we've filled the
         * request packet */
-        while (1) {
+       while (1) {
                /* if we've copied all the data requested, we're done */
-                if (count <= 0) break;
+               if (count <= 0) break;
 
                /* handle over quota or out of space */
-               if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA
-                                  | CM_SCACHEFLAG_OUTOFSPACE)) {
+               if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE)) {
                        *writtenp = written;
                        break;
                }
                 
-                /* otherwise, load up a buffer of data */
-                thyper.HighPart = offset.HighPart;
-                thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1);
-                if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
+               /* otherwise, load up a buffer of data */
+               thyper.HighPart = offset.HighPart;
+               thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1);
+               if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
                        /* wrong buffer */
-                        if (bufferp) {
+                       if (bufferp) {
                                lock_ReleaseMutex(&bufferp->mx);
-                               buf_Release(bufferp);
-                                bufferp = NULL;
-                       }
+                               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);
 
-                        lock_ObtainMutex(&bufferp->mx);
-                        lock_ObtainMutex(&scp->mx);
-                        if (code) goto done;
+                       lock_ObtainMutex(&bufferp->mx);
+                       lock_ObtainMutex(&scp->mx);
+                       if (code) goto done;
 
-                        bufferOffset = thyper;
+                       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, 0,
-                                       CM_SCACHESYNC_NEEDCALLBACK
-                                       | CM_SCACHESYNC_WRITE
-                                        | CM_SCACHESYNC_BUFLOCKED);
-                               if (code) goto done;
+                                                                CM_SCACHESYNC_NEEDCALLBACK
+                                                                | CM_SCACHESYNC_WRITE
+                                                                | CM_SCACHESYNC_BUFLOCKED);
+                               if (code) 
+                                       goto done;
                                 
                                /* If we're overwriting the entire buffer, or
                                 * if we're writing at or past EOF, mark the
                                 * buffer as current so we don't call
                                 * cm_GetBuffer.  This skips the fetch from the
                                 * server in those cases where we're going to 
-                                * obliterate all the data in the buffer anyway,
+                                * obliterate all the data in the buffer anyway,
                                 * or in those cases where there is no useful
                                 * data at the server to start with.
-                                 *
-                                 * Use minLength instead of scp->length, since
+                                *
+                                * Use minLength instead of scp->length, since
                                 * the latter has already been updated by this
                                 * call.
-                                */
+                                */
                                if (LargeIntegerGreaterThanOrEqualTo(
                                        bufferp->offset, minLength)
                                    || LargeIntegerEqualTo(offset, bufferp->offset)
@@ -3967,76 +5039,83 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                                        bufferp->dataVersion = scp->dataVersion;
                                }
 
-                                if (cm_HaveBuffer(scp, bufferp, 1)) break;
-                                
-                                /* otherwise, load the buffer and try again */
-                                lock_ReleaseMutex(&bufferp->mx);
-                                code = cm_GetBuffer(scp, bufferp, NULL, userp,
-                                                   &req);
-                                lock_ReleaseMutex(&scp->mx);
-                                lock_ObtainMutex(&bufferp->mx);
+                               if (cm_HaveBuffer(scp, bufferp, 1)) break;
+
+                               /* otherwise, load the buffer and try again */
+                               lock_ReleaseMutex(&bufferp->mx);
+                               code = cm_GetBuffer(scp, bufferp, NULL, userp,
+                                                                       &req);
+                               lock_ReleaseMutex(&scp->mx);
+                               lock_ObtainMutex(&bufferp->mx);
                                lock_ObtainMutex(&scp->mx);
-                                if (code) break;
-                        }
-                        if (code) {
+                               if (code) break;
+                       }
+                       if (code) {
                                lock_ReleaseMutex(&bufferp->mx);
                                buf_Release(bufferp);
-                                bufferp = NULL;
+                               bufferp = NULL;
                                goto done;
                        }
-                }      /* if (wrong buffer) ... */
+               }       /* if (wrong buffer) ... */
                 
-                /* now we have the right buffer loaded.  Copy out the
-                 * data from here to the user's buffer.
-                 */
+               /* now we have the right buffer loaded.  Copy out the
+                * data from here to the user's buffer.
+                */
                bufIndex = offset.LowPart & (buf_bufferSize - 1);
 
                /* and figure out how many bytes we want from this buffer */
-                nbytes = buf_bufferSize - bufIndex;    /* what remains in buffer */
-                if (nbytes > count) nbytes = count;    /* don't go past end of request */
+               nbytes = buf_bufferSize - bufIndex;     /* what remains in buffer */
+               if (nbytes > count) 
+                       nbytes = count; /* don't go past end of request */
                
-                /* now copy the data */
-                memcpy(bufferp->datap + bufIndex, op, nbytes);
-                buf_SetDirty(bufferp);
+               /* now copy the data */
+#ifdef DJGPP
+               if (dosflag)
+                       dosmemget((dos_ptr)op, nbytes, bufferp->datap + bufIndex);
+               else
+#endif /* DJGPP */
+                       memcpy(bufferp->datap + bufIndex, op, nbytes);
+               buf_SetDirty(bufferp);
 
                /* and record the last writer */
                if (bufferp->userp != userp) {
-                       if (bufferp->userp) cm_ReleaseUser(bufferp->userp);
-                       bufferp->userp = userp;
-                       cm_HoldUser(userp);
+                       cm_HoldUser(userp);
+                       if (bufferp->userp) 
+                cm_ReleaseUser(bufferp->userp);
+                       bufferp->userp = userp;
                }
                 
                /* adjust counters, pointers, etc. */
-                op += nbytes;
-                count -= nbytes;
+               op += nbytes;
+               count -= nbytes;
                written += nbytes;
-                thyper.LowPart = nbytes;
-                thyper.HighPart = 0;
-                offset = LargeIntegerAdd(thyper, offset);
-        } /* while 1 */
+               thyper.LowPart = nbytes;
+               thyper.HighPart = 0;
+               offset = LargeIntegerAdd(thyper, offset);
+       } /* while 1 */
 
-done:
+  done:
        lock_ReleaseMutex(&scp->mx);
        lock_ReleaseMutex(&fidp->mx);
-        if (bufferp) {
+       if (bufferp) {
                lock_ReleaseMutex(&bufferp->mx);
-               buf_Release(bufferp);
+               buf_Release(bufferp);
        }
 
        if (code == 0 && filter != 0 && (fidp->flags & SMB_FID_NTOPEN)
            && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) {
                smb_NotifyChange(FILE_ACTION_MODIFIED, filter,
-                                fidp->NTopen_dscp, fidp->NTopen_pathp,
-                                NULL, TRUE);
+                                                fidp->NTopen_dscp, fidp->NTopen_pathp,
+                                                NULL, TRUE);
        }
 
-        if (code == 0 && doWriteBack) {
+       if (code == 0 && doWriteBack) {
                lock_ObtainMutex(&scp->mx);
                cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
                lock_ReleaseMutex(&scp->mx);
-                       cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
-                               writeBackOffset.HighPart, cm_chunkSize, 0, userp);
-        }
+               cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
+                                                  writeBackOffset.HighPart, cm_chunkSize, 0, userp);
+       }
 
        return code;
 }
@@ -4044,54 +5123,54 @@ done:
 long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        osi_hyper_t offset;
-        long count, written = 0;
-        unsigned short fd;
-        smb_fid_t *fidp;
-        long code;
-        cm_user_t *userp;
-        cm_attr_t truncAttr;   /* attribute struct used for truncating file */
-        char *op;
-        long inDataBlockCount;
-
-        fd = smb_GetSMBParm(inp, 0);
-        count = smb_GetSMBParm(inp, 1);
-        offset.HighPart = 0;   /* too bad */
-        offset.LowPart = smb_GetSMBParm(inp, 2) | (smb_GetSMBParm(inp, 3) << 16);
-
-        op = smb_GetSMBData(inp, NULL);
+    long count, written = 0;
+    unsigned short fd;
+    smb_fid_t *fidp;
+    long code = 0;
+    cm_user_t *userp;
+    cm_attr_t truncAttr;       /* attribute struct used for truncating file */
+    char *op;
+    int inDataBlockCount;
+
+    fd = smb_GetSMBParm(inp, 0);
+    count = smb_GetSMBParm(inp, 1);
+    offset.HighPart = 0;       /* too bad */
+    offset.LowPart = smb_GetSMBParm(inp, 2) | (smb_GetSMBParm(inp, 3) << 16);
+
+    op = smb_GetSMBData(inp, NULL);
        op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
 
-        osi_Log3(afsd_logp, "smb_ReceiveCoreWrite fd %d, off 0x%x, size 0x%x",
-               fd, offset.LowPart, count);
+    osi_Log3(smb_logp, "smb_ReceiveCoreWrite 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;
-        }
+    }
         
-        if (fidp->flags & SMB_FID_IOCTL)
-               return smb_IoctlWrite(fidp, vcp, inp, outp);
+    if (fidp->flags & SMB_FID_IOCTL)
+        return smb_IoctlWrite(fidp, vcp, inp, outp);
         
        userp = smb_GetUser(vcp, inp);
 
        /* special case: 0 bytes transferred means truncate to this position */
-        if (count == 0) {
+    if (count == 0) {
                cm_req_t req;
 
                cm_InitReq(&req);
 
                truncAttr.mask = CM_ATTRMASK_LENGTH;
-                truncAttr.length.LowPart = offset.LowPart;
-                truncAttr.length.HighPart = 0;
+        truncAttr.length.LowPart = offset.LowPart;
+        truncAttr.length.HighPart = 0;
                lock_ObtainMutex(&fidp->mx);
-                code = cm_SetAttr(fidp->scp, &truncAttr, userp, &req);
+        code = cm_SetAttr(fidp->scp, &truncAttr, userp, &req);
                lock_ReleaseMutex(&fidp->mx);
                smb_SetSMBParm(outp, 0, /* count */ 0);
-               smb_SetSMBDataLength(outp, 0);
+        smb_SetSMBDataLength(outp, 0);
                fidp->flags |= SMB_FID_LENGTHSETDONE;
-                goto done;
-        }
+        goto done;
+    }
 
        /*
         * Work around bug in NT client
@@ -4108,19 +5187,23 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                fidp->scp->clientModTime = time(NULL);
        }
 
+#ifndef DJGPP
        code = smb_WriteData(fidp, &offset, count, op, userp, &written);
+#else /* DJGPP */
+       code = smb_WriteData(fidp, &offset, count, op, userp, &written, FALSE);
+#endif /* !DJGPP */
        if (code == 0 && written < count)
                code = CM_ERROR_PARTIALWRITE;
 
        /* set the packet data length to 3 bytes for the data block header,
-         * plus the size of the data.
-         */
+     * plus the size of the data.
+     */
        smb_SetSMBParm(outp, 0, written);
-        smb_SetSMBDataLength(outp, 0);
+    smb_SetSMBDataLength(outp, 0);
 
-done:
-        smb_ReleaseFID(fidp);
-        cm_ReleaseUser(userp);
+  done:
+    smb_ReleaseFID(fidp);
+    cm_ReleaseUser(userp);
 
        return code;
 }
@@ -4131,22 +5214,32 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        unsigned short fd;
        smb_fid_t *fidp;
        cm_user_t *userp;
+#ifndef DJGPP
        char *rawBuf;
-       int written = 0;
-       long code;
+#else /* DJGPP */
+       dos_ptr rawBuf;
+#endif /* !DJGPP */
+       long written = 0;
+       long code = 0;
 
        fd = smb_GetSMBParm(inp, 0);
        fidp = smb_FindFID(vcp, fd, 0);
 
-       osi_Log2(afsd_logp, "Completing Raw Write offset %x count %x",
-                rwcp->offset.LowPart, rwcp->count);
+       osi_Log2(smb_logp, "Completing Raw Write offset %x count %x",
+                rwcp->offset.LowPart, rwcp->count);
 
        userp = smb_GetUser(vcp, inp);
 
+#ifndef DJGPP
        rawBuf = rwcp->buf;
-
        code = smb_WriteData(fidp, &rwcp->offset, rwcp->count, rawBuf, userp,
-                            &written);
+                                                &written);
+#else /* DJGPP */
+       rawBuf = (dos_ptr) rwcp->buf;
+       code = smb_WriteData(fidp, &rwcp->offset, rwcp->count,
+                         (unsigned char *) rawBuf, userp,
+                         &written, TRUE);
+#endif /* !DJGPP */
 
        if (rwcp->writeMode & 0x1) {    /* synchronous */
                smb_t *op;
@@ -4163,13 +5256,17 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                lock_ObtainMutex(&fidp->mx);
                fidp->raw_writers--;
                if (fidp->raw_writers == 0)
-                       SetEvent(fidp->raw_write_event);
+                       thrd_SetEvent(fidp->raw_write_event);
                lock_ReleaseMutex(&fidp->mx);
        }
 
        /* Give back raw buffer */
        lock_ObtainMutex(&smb_RawBufLock);
+#ifndef DJGPP
        *((char **)rawBuf) = smb_RawBufs;
+#else /* DJGPP */
+    _farpokel(_dos_ds, rawBuf, smb_RawBufs);
+#endif /* !DJGPP */
        smb_RawBufs = rawBuf;
        lock_ReleaseMutex(&smb_RawBufLock);
 
@@ -4185,35 +5282,39 @@ long smb_ReceiveCoreWriteRawDummy(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
 long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, raw_write_cont_t *rwcp)
 {
        osi_hyper_t offset;
-        long count, written = 0;
+    long count, written = 0;
        long totalCount;
-        unsigned short fd;
-        smb_fid_t *fidp;
-        long code;
-        cm_user_t *userp;
-        char *op;
+    unsigned short fd;
+    smb_fid_t *fidp;
+    long code = 0;
+    cm_user_t *userp;
+    char *op;
        unsigned short writeMode;
+#ifndef DJGPP
        char *rawBuf;
+#else /* DJGPP */
+    dos_ptr rawBuf;
+#endif /* !DJGPP */
 
-        fd = smb_GetSMBParm(inp, 0);
+    fd = smb_GetSMBParm(inp, 0);
        totalCount = smb_GetSMBParm(inp, 1);
-        count = smb_GetSMBParm(inp, 10);
-        offset.HighPart = 0;   /* too bad */
-        offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
+    count = smb_GetSMBParm(inp, 10);
+    offset.HighPart = 0;       /* too bad */
+    offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
        writeMode = smb_GetSMBParm(inp, 7);
 
        op = (char *) inp->data;
        op += smb_GetSMBParm(inp, 11);
 
-        osi_Log4(afsd_logp,
-               "smb_ReceiveCoreWriteRaw fd %d, off 0x%x, size 0x%x, WriteMode 0x%x",
-               fd, offset.LowPart, count, writeMode);
+    osi_Log4(smb_logp,
+             "smb_ReceiveCoreWriteRaw fd %d, off 0x%x, size 0x%x, WriteMode 0x%x",
+             fd, offset.LowPart, count, writeMode);
         
        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;
-        }
+    }
         
        userp = smb_GetUser(vcp, inp);
 
@@ -4232,7 +5333,11 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                fidp->scp->clientModTime = time(NULL);
        }
 
+#ifndef DJGPP
        code = smb_WriteData(fidp, &offset, count, op, userp, &written);
+#else /* DJGPP */
+       code = smb_WriteData(fidp, &offset, count, op, userp, &written, FALSE);
+#endif /* !DJGPP */
        if (code == 0 && written < count)
                code = CM_ERROR_PARTIALWRITE;
 
@@ -4243,18 +5348,23 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                if (smb_RawBufs) {
                        /* Get a raw buf, from head of list */
                        rawBuf = smb_RawBufs;
+#ifndef DJGPP
                        smb_RawBufs = *(char **)smb_RawBufs;
+#else /* DJGPP */
+            smb_RawBufs = _farpeekl(_dos_ds, smb_RawBufs);
+#endif /* !DJGPP */
                }
                else
                        code = CM_ERROR_USESTD;
-               lock_ReleaseMutex(&smb_RawBufLock);
+               
+        lock_ReleaseMutex(&smb_RawBufLock);
        }
 
        /* Don't allow a premature Close */
        if (code == 0 && (writeMode & 1) == 0) {
                lock_ObtainMutex(&fidp->mx);
                fidp->raw_writers++;
-               ResetEvent(fidp->raw_write_event);
+               thrd_ResetEvent(fidp->raw_write_event);
                lock_ReleaseMutex(&fidp->mx);
        }
 
@@ -4278,10 +5388,10 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        rwcp->alreadyWritten = written;
 
        /* set the packet data length to 3 bytes for the data block header,
-         * plus the size of the data.
-         */
+     * plus the size of the data.
+     */
        smb_SetSMBParm(outp, 0, 0xffff);
-        smb_SetSMBDataLength(outp, 0);
+    smb_SetSMBDataLength(outp, 0);
 
        return 0;
 }
@@ -4289,300 +5399,316 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 long smb_ReceiveCoreRead(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;
+    long count, finalCount;
+    unsigned short fd;
+    smb_fid_t *fidp;
+    long code = 0;
+    cm_user_t *userp;
+    char *op;
         
-        fd = smb_GetSMBParm(inp, 0);
-        count = smb_GetSMBParm(inp, 1);
-        offset.HighPart = 0;   /* too bad */
-        offset.LowPart = smb_GetSMBParm(inp, 2) | (smb_GetSMBParm(inp, 3) << 16);
+    fd = smb_GetSMBParm(inp, 0);
+    count = smb_GetSMBParm(inp, 1);
+    offset.HighPart = 0;       /* too bad */
+    offset.LowPart = smb_GetSMBParm(inp, 2) | (smb_GetSMBParm(inp, 3) << 16);
         
-        osi_Log3(afsd_logp, "smb_ReceiveCoreRead fd %d, off 0x%x, size 0x%x",
-               fd, offset.LowPart, count);
+    osi_Log3(smb_logp, "smb_ReceiveCoreRead 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;
-        }
+    }
         
-        if (fidp->flags & SMB_FID_IOCTL) {
+    if (fidp->flags & SMB_FID_IOCTL) {
                return smb_IoctlRead(fidp, vcp, inp, outp);
-        }
+    }
         
        userp = smb_GetUser(vcp, inp);
 
        /* remember this for final results */
-        smb_SetSMBParm(outp, 0, count);
-        smb_SetSMBParm(outp, 1, 0);
-        smb_SetSMBParm(outp, 2, 0);
-        smb_SetSMBParm(outp, 3, 0);
-        smb_SetSMBParm(outp, 4, 0);
+    smb_SetSMBParm(outp, 0, count);
+    smb_SetSMBParm(outp, 1, 0);
+    smb_SetSMBParm(outp, 2, 0);
+    smb_SetSMBParm(outp, 3, 0);
+    smb_SetSMBParm(outp, 4, 0);
 
        /* set the packet data length to 3 bytes for the data block header,
-         * plus the size of the data.
-         */
-        smb_SetSMBDataLength(outp, count+3);
+     * plus the size of the data.
+     */
+    smb_SetSMBDataLength(outp, count+3);
         
        /* 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 emit the data block header: 1 byte of type and 2 bytes of length */
-        *op++ = 1;     /* data block marker */
-        *op++ = (unsigned char) (count & 0xff);
-        *op++ = (unsigned char) ((count >> 8) & 0xff);
+    *op++ = 1; /* data block marker */
+    *op++ = (unsigned char) (count & 0xff);
+    *op++ = (unsigned char) ((count >> 8) & 0xff);
                 
+#ifndef DJGPP
        code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount);
+#else /* DJGPP */
+    code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount, FALSE);
+#endif /* !DJGPP */
 
        /* fix some things up */
        smb_SetSMBParm(outp, 0, finalCount);
        smb_SetSMBDataLength(outp, finalCount+3);
 
-        smb_ReleaseFID(fidp);
+    smb_ReleaseFID(fidp);
        
-        cm_ReleaseUser(userp);
-        return code;
+    cm_ReleaseUser(userp);
+    return code;
 }
 
 long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-        long code;
+    long code = 0;
        cm_space_t *spacep;
-        char *tp;
-        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;
-        char *lastNamep;
-        int caseFold;
+    char *tp;
+    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;
+    char *lastNamep;
+    int caseFold;
        char *tidPathp;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-        scp = NULL;
+    scp = NULL;
         
        /* compute initial mode bits based on read-only flag in attributes */
-        initialModeBits = 0777;
+    initialModeBits = 0777;
         
        tp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(tp, &tp);
+    pathp = smb_ParseASCIIBlock(tp, &tp);
 
        if (strcmp(pathp, "\\") == 0)
                return CM_ERROR_EXISTS;
 
        spacep = inp->spacep;
-        smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+    smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
        userp = smb_GetUser(vcp, inp);
 
-               caseFold = CM_FLAG_CASEFOLD;
+    caseFold = CM_FLAG_CASEFOLD;
 
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
 
        code = cm_NameI(cm_rootSCachep, spacep->data,
-               caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
-               userp, tidPathp, &req, &dscp);
+                    caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
+                    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
+    /* otherwise, scp points to the parent directory.  Do a lookup, and
         * fail if we find it.  Otherwise, we do the create.
-         */
-        if (!lastNamep) lastNamep = pathp;
-        else lastNamep++;
-        code = cm_Lookup(dscp, lastNamep, caseFold, userp, &req, &scp);
-        if (scp) cm_ReleaseSCache(scp);
-        if (code != CM_ERROR_NOSUCHFILE) {
-               if (code == 0) code = CM_ERROR_EXISTS;
+     */
+    if (!lastNamep) 
+        lastNamep = pathp;
+    else 
+        lastNamep++;
+    code = cm_Lookup(dscp, lastNamep, 0, userp, &req, &scp);
+    if (scp) cm_ReleaseSCache(scp);
+    if (code != CM_ERROR_NOSUCHFILE) {
+        if (code == 0) code = CM_ERROR_EXISTS;
                cm_ReleaseSCache(dscp);
-                cm_ReleaseUser(userp);
-                return code;
-        }
+        cm_ReleaseUser(userp);
+        return code;
+    }
         
        setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
        setAttr.clientModTime = time(NULL);
        code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req);
        if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                smb_NotifyChange(FILE_ACTION_ADDED,
-                                FILE_NOTIFY_CHANGE_DIR_NAME,
-                                dscp, lastNamep, NULL, TRUE);
+                         FILE_NOTIFY_CHANGE_DIR_NAME,
+                         dscp, lastNamep, NULL, TRUE);
         
        /* we don't need this any longer */
        cm_ReleaseSCache(dscp);
 
-        if (code) {
+    if (code) {
                /* something went wrong creating or truncating the file */
-                cm_ReleaseUser(userp);
-                return code;
-        }
+        cm_ReleaseUser(userp);
+        return code;
+    }
         
        /* otherwise we succeeded */
-        smb_SetSMBDataLength(outp, 0);
-        cm_ReleaseUser(userp);
+    smb_SetSMBDataLength(outp, 0);
+    cm_ReleaseUser(userp);
 
-        return 0;
+    return 0;
 }
 
 BOOL smb_IsLegalFilename(char *filename)
 {
-        /* 
-         *  Find the longest substring of filename that does not contain
-         *  any of the chars in illegalChars.  If that substring is less
-         *  than the length of the whole string, then one or more of the
-         *  illegal chars is in filename. 
-         */
-        if (strcspn(filename, illegalChars) < strlen(filename))
-                return FALSE;
-
-        return TRUE;
+    /* 
+     *  Find the longest substring of filename that does not contain
+     *  any of the chars in illegalChars.  If that substring is less
+     *  than the length of the whole string, then one or more of the
+     *  illegal chars is in filename. 
+     */
+    if (strcspn(filename, illegalChars) < strlen(filename))
+        return FALSE;
+
+    return TRUE;
 }        
 
 long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-        long code;
+    long code = 0;
        cm_space_t *spacep;
-        char *tp;
-        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;
-        int caseFold;
-        long dosTime;
+    char *tp;
+    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;
+    int caseFold;
+    long dosTime;
        char *tidPathp;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-        scp = NULL;
-        excl = (inp->inCom == 0x03)? 0 : 1;
+    scp = NULL;
+    excl = (inp->inCom == 0x03)? 0 : 1;
         
-        attributes = smb_GetSMBParm(inp, 0);
-        dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
+    attributes = smb_GetSMBParm(inp, 0);
+    dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 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;
         
        tp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(tp, &tp);
+    pathp = smb_ParseASCIIBlock(tp, &tp);
 
        spacep = inp->spacep;
-        smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+    smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
        userp = smb_GetUser(vcp, inp);
 
-               caseFold = CM_FLAG_CASEFOLD;
+    caseFold = CM_FLAG_CASEFOLD;
 
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
-               userp, tidPathp, &req, &dscp);
+                    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
+    /* otherwise, scp points to the parent directory.  Do a lookup, and
         * truncate the file if we find it, otherwise we create the file.
-         */
-        if (!lastNamep) lastNamep = pathp;
-        else lastNamep++;
-
-        if (!smb_IsLegalFilename(lastNamep))
-                return CM_ERROR_BADNTFILENAME;
-
-        code = cm_Lookup(dscp, lastNamep, caseFold, userp, &req, &scp);
-        if (code && code != CM_ERROR_NOSUCHFILE) {
+     */
+    if (!lastNamep) lastNamep = pathp;
+    else lastNamep++;
+
+    if (!smb_IsLegalFilename(lastNamep))
+        return CM_ERROR_BADNTFILENAME;
+
+    osi_Log1(smb_logp, "SMB receive create [%s]", osi_LogSaveString( smb_logp, pathp ));
+#ifdef DEBUG_VERBOSE
+    {
+        char *hexp;
+        hexp = osi_HexifyString( lastNamep );
+        DEBUG_EVENT2("AFS", "CoreCreate H[%s] A[%s]", hexp, lastNamep );
+        free(hexp);
+    }
+#endif    
+
+    code = cm_Lookup(dscp, lastNamep, 0, 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.
-         */
+    /* 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) {
                if (excl) {
                        /* oops, file shouldn't be there */
-                        cm_ReleaseSCache(dscp);
-                        cm_ReleaseSCache(scp);
-                        cm_ReleaseUser(userp);
-                        return CM_ERROR_EXISTS;
-                }
+            cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
+            return CM_ERROR_EXISTS;
+        }
 
                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);
-        }
-        else {
+    }
+    else {
                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, caseFold, userp,
-                                        &req, &scp);
-                        if (code == 0) {
+             */
+            code = cm_Lookup(dscp, lastNamep, caseFold, userp,
+                             &req, &scp);
+            if (code == 0) {
                                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);
+            }
         }
+    }
         
        /* we don't need this any longer */
        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 only open files */
        if (scp->fileType != CM_SCACHETYPE_FILE) {
                cm_ReleaseSCache(scp);
-                cm_ReleaseUser(userp);
-                return CM_ERROR_ISDIR;
+        cm_ReleaseUser(userp);
+        return CM_ERROR_ISDIR;
        }
 
-        /* now all we have to do is open the file itself */
-        fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
-        osi_assert(fidp);
+    /* 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;
         
        /* always create it open for read/write */
        fidp->flags |= (SMB_FID_OPENREAD | SMB_FID_OPENWRITE);
@@ -4590,65 +5716,65 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        smb_ReleaseFID(fidp);
         
        smb_SetSMBParm(outp, 0, fidp->fid);
-        smb_SetSMBDataLength(outp, 0);
+    smb_SetSMBDataLength(outp, 0);
 
        cm_Open(scp, 0, userp);
 
-        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_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-        long code;
-        long offset;
-        int whence;
-        unsigned short fd;
-        smb_fid_t *fidp;
-        cm_scache_t *scp;
-        cm_user_t *userp;
+    long code = 0;
+    long offset;
+    int whence;
+    unsigned short fd;
+    smb_fid_t *fidp;
+    cm_scache_t *scp;
+    cm_user_t *userp;
        cm_req_t req;
 
        cm_InitReq(&req);
         
-        fd = smb_GetSMBParm(inp, 0);
+    fd = smb_GetSMBParm(inp, 0);
        whence = smb_GetSMBParm(inp, 1);
-        offset = smb_GetSMBParm(inp, 2) | (smb_GetSMBParm(inp, 3) << 16);
+    offset = smb_GetSMBParm(inp, 2) | (smb_GetSMBParm(inp, 3) << 16);
         
        /* try to find the file descriptor */
        fd = smb_ChainFID(fd, inp);
-        fidp = smb_FindFID(vcp, fd, 0);
-        if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+    fidp = smb_FindFID(vcp, fd, 0);
+    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
                return CM_ERROR_BADFD;
-        }
+    }
        
        userp = smb_GetUser(vcp, inp);
 
-        lock_ObtainMutex(&fidp->mx);
-        scp = fidp->scp;
+    lock_ObtainMutex(&fidp->mx);
+    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 == 0) {
                if (whence == 1) {
-                       /* offset from current offset */
-                       offset += fidp->offset;
+            /* offset from current offset */
+            offset += fidp->offset;
                }
                else if (whence == 2) {
-                       /* offset from current EOF */
-                        offset += scp->length.LowPart;
+            /* offset from current EOF */
+            offset += scp->length.LowPart;
                }
-                fidp->offset = offset;
-                smb_SetSMBParm(outp, 0, offset & 0xffff);
-                smb_SetSMBParm(outp, 1, (offset>>16) & 0xffff);
-                smb_SetSMBDataLength(outp, 0);
-        }
+        fidp->offset = offset;
+        smb_SetSMBParm(outp, 0, offset & 0xffff);
+        smb_SetSMBParm(outp, 1, (offset>>16) & 0xffff);
+        smb_SetSMBDataLength(outp, 0);
+    }
        lock_ReleaseMutex(&scp->mx);
-        lock_ReleaseMutex(&fidp->mx);
-        smb_ReleaseFID(fidp);
-        cm_ReleaseUser(userp);
-        return code;
+    lock_ReleaseMutex(&fidp->mx);
+    smb_ReleaseFID(fidp);
+    cm_ReleaseUser(userp);
+    return code;
 }
 
 /* dispatch all of the requests received in a packet.  Due to chaining, this may
@@ -4657,20 +5783,19 @@ long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        NCB *ncbp, raw_write_cont_t *rwcp)
 {
-        static showErrors = 1;
-        smb_dispatch_t *dp;
-        smb_t *smbp;
-        unsigned long code;
-        unsigned char *outWctp;
-        int nparms;                    /* # of bytes of parameters */
-        char tbuffer[200];
-        int nbytes;                    /* bytes of data, excluding count */
-        int temp;
-        unsigned char *tp;
-        unsigned short errCode;
+    smb_dispatch_t *dp;
+    smb_t *smbp;
+    unsigned long code = 0;
+    unsigned char *outWctp;
+    int nparms;                        /* # of bytes of parameters */
+    char tbuffer[200];
+    int nbytes;                        /* bytes of data, excluding count */
+    int temp;
+    unsigned char *tp;
+    unsigned short errCode;
        unsigned long NTStatus;
-        int noSend;
-        unsigned char errClass;
+    int noSend;
+    unsigned char errClass;
        unsigned int oldGen;
        DWORD oldTime, newTime;
 
@@ -4678,17 +5803,18 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        smbp = (smb_t *) inp->data;
 
        if (!(outp->flags & SMB_PACKETFLAG_SUSPENDED)) {
-               /* setup the basic parms for the initial request in the packet */
+        /* setup the basic parms for the initial request in the packet */
                inp->inCom = smbp->com;
-               inp->wctp = &smbp->wct;
-               inp->inCount = 0;
+        inp->wctp = &smbp->wct;
+        inp->inCount = 0;
                inp->ncb_length = ncbp->ncb_length;
        }
-        noSend = 0;
+    noSend = 0;
 
        /* Sanity check */
        if (ncbp->ncb_length < offsetof(struct smb, vdata)) {
                /* log it and discard it */
+#ifndef DJGPP
                HANDLE h;
                char *ptbuf[1];
                char s[100];
@@ -4698,23 +5824,28 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1007, NULL,
                        1, ncbp->ncb_length, ptbuf, inp);
                DeregisterEventSource(h);
+#else /* DJGPP */
+        osi_Log1(smb_logp, "SMB message too short, len %d",
+                 ncbp->ncb_length);
+#endif /* !DJGPP */
+
                return;
        }
 
        /* We are an ongoing op */
-       InterlockedIncrement(&ongoingOps);
+       thrd_Increment(&ongoingOps);
 
-        /* set up response packet for receiving output */
+    /* set up response packet for receiving output */
        if (!(outp->flags & SMB_PACKETFLAG_SUSPENDED))
-               smb_FormatResponsePacket(vcp, inp, outp);
-        outWctp = outp->wctp;
+        smb_FormatResponsePacket(vcp, inp, outp);
+    outWctp = outp->wctp;
 
        /* Remember session generation number and time */
        oldGen = sessionGen;
        oldTime = GetCurrentTime();
 
        while(inp->inCom != 0xff) {
-                dp = &smb_dispatchTable[inp->inCom];
+        dp = &smb_dispatchTable[inp->inCom];
 
                if (outp->flags & SMB_PACKETFLAG_SUSPENDED) {
                        outp->flags &= ~SMB_PACKETFLAG_SUSPENDED;
@@ -4722,108 +5853,134 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                        goto resume;
                }
 
-                /* process each request in the packet; inCom, wctp and inCount
-                 * are already set up.
-                 */
-               osi_Log2(afsd_logp, "SMB received op 0x%x lsn %d", inp->inCom,
-                        ncbp->ncb_lsn);
+        /* process each request in the packet; inCom, wctp and inCount
+         * are already set up.
+         */
+               osi_Log2(smb_logp, "SMB received op 0x%x lsn %d", inp->inCom,
+                 ncbp->ncb_lsn);
 
                /* now do the dispatch */
                /* start by formatting the response record a little, as a default */
-                if (dp->flags & SMB_DISPATCHFLAG_CHAINED) {
+        if (dp->flags & SMB_DISPATCHFLAG_CHAINED) {
                        outWctp[0] = 2;
-                        outWctp[1] = 0xff;     /* no operation */
-                        outWctp[2] = 0;                /* padding */
-                        outWctp[3] = 0;
-                        outWctp[4] = 0;
-                }
+            outWctp[1] = 0xff; /* no operation */
+            outWctp[2] = 0;            /* padding */
+            outWctp[3] = 0;
+            outWctp[4] = 0;
+        }
                else {
                        /* not a chained request, this is a more reasonable default */
-                       outWctp[0] = 0; /* wct of zero */
-                       outWctp[1] = 0; /* and bcc (word) of zero */
-                       outWctp[2] = 0;
-               }
+            outWctp[0] = 0;    /* wct of zero */
+            outWctp[1] = 0;    /* and bcc (word) of zero */
+            outWctp[2] = 0;
+               }   
 
                /* once set, stays set.  Doesn't matter, since we never chain
-                 * "no response" calls.
-                 */
+         * "no response" calls.
+         */
                if (dp->flags & SMB_DISPATCHFLAG_NORESPONSE)
-                       noSend = 1;
+            noSend = 1;
 
-                if (dp->procp) {
+        if (dp->procp) {
                        /* we have a recognized operation */
 
                        if (inp->inCom == 0x1d)
                                /* Raw Write */
                                code = smb_ReceiveCoreWriteRaw (vcp, inp, outp,
-                                                               rwcp);
-                       else
-                               code = (*(dp->procp)) (vcp, inp, outp);
+                                                rwcp);
+                       else {
+                                       osi_LogEvent("AFS Dispatch %s",(myCrt_Dispatch(inp->inCom)),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
+                                       osi_Log4(smb_logp,"Dispatch %s vcp[%x] lana[%d] lsn[%d]",(myCrt_Dispatch(inp->inCom)),vcp,vcp->lana,vcp->lsn);
+                                       code = (*(dp->procp)) (vcp, inp, outp);
+                                       osi_LogEvent("AFS Dispatch return",NULL,"Code[%d]",(code==0)?0:code-CM_ERROR_BASE);
+                                       osi_Log1(smb_logp,"Dispatch return  code[%d]",(code==0)?0:code-CM_ERROR_BASE);
+            }
 
                        if (oldGen != sessionGen) {
+#ifndef DJGPP
                                HANDLE h;
                                char *ptbuf[1];
                                char s[100];
                                newTime = GetCurrentTime();
                                h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
                                sprintf(s, "Pkt straddled session startup, took %d ms, ncb length %d",
-                                       newTime - oldTime, ncbp->ncb_length);
+                        newTime - oldTime, ncbp->ncb_length);
                                ptbuf[0] = s;
                                ReportEvent(h, EVENTLOG_WARNING_TYPE, 0,
-                               1005, NULL, 1, ncbp->ncb_length, ptbuf, smbp);
+                            1005, NULL, 1, ncbp->ncb_length, ptbuf, smbp);
                                DeregisterEventSource(h);
+#else /* DJGPP */
+                               osi_Log1(smb_logp, "Pkt straddled session startup, "
+                         "ncb length %d", ncbp->ncb_length);
+#endif /* !DJGPP */
                        }
-                }
-                else {
+        }
+        else {
                        /* bad opcode, fail the request, after displaying it */
+#ifdef NOTSERVICE
+            smb_LogPacket(inp);
+#endif  /* NOTSERVICE */
+
+#ifndef DJGPP
                        if (showErrors) {
                                sprintf(tbuffer, "Received bad SMB req 0x%x", inp->inCom);
-                               code = (*smb_MBfunc)(NULL, tbuffer, "Cancel: don't show again",
-                                       MB_OKCANCEL);
-                               if (code == IDCANCEL) showErrors = 0;
+                code = (*smb_MBfunc)(NULL, tbuffer, "Cancel: don't show again",
+                                     MB_OKCANCEL|MB_SERVICE_NOTIFICATION);
+                if (code == IDCANCEL) showErrors = 0;
                        }
-                        code = CM_ERROR_BADOP;
-                }
+#endif /* DJGPP */
+            code = CM_ERROR_BADOP;
+        }
 
                /* catastrophic failure:  log as much as possible */
                if (code == CM_ERROR_BADSMB) {
+#ifndef DJGPP
                        HANDLE h;
                        char *ptbuf[1];
                        char s[100];
 
                        osi_Log1(smb_logp,
-                               "Invalid SMB, ncb_length %d",
-                               ncbp->ncb_length);
+                      "Invalid SMB, ncb_length %d",
+                      ncbp->ncb_length);
 
                        h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
                        sprintf(s, "Invalid SMB message, length %d",
-                               ncbp->ncb_length);
+                     ncbp->ncb_length);
                        ptbuf[0] = s;
                        ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1002, NULL,
-                                   1, ncbp->ncb_length, ptbuf, smbp);
+                         1, ncbp->ncb_length, ptbuf, smbp);
                        DeregisterEventSource(h);
+#ifdef NOTSERVICE
+            smb_LogPacket(inp);
+#endif /* NOTSERVICE */
+#else /* DJGPP */
+            osi_Log1(smb_logp, "Invalid SMB message, length %d",
+                     ncbp->ncb_length);
+#endif /* !DJGPP */
 
                        code = CM_ERROR_INVAL;
                }
 
                if (outp->flags & SMB_PACKETFLAG_NOSEND) {
-                       InterlockedDecrement(&ongoingOps);
+                       thrd_Decrement(&ongoingOps);
                        return;
                }
 
-resume:
+      resume:
                /* now, if we failed, turn the current response into an empty
-                * one, and fill in the response packet's error code.
-                 */
+         * one, and fill in the response packet's error code.
+         */
                if (code) {
                        if (vcp->flags & SMB_VCFLAG_STATUS32) {
                                smb_MapNTError(code, &NTStatus);
                                outWctp = outp->wctp;
                                smbp = (smb_t *) &outp->data;
                                if (code != CM_ERROR_PARTIALWRITE
-                                   && code != CM_ERROR_BUFFERTOOSMALL) {
+                                   && code != CM_ERROR_BUFFERTOOSMALL 
+                    && code != CM_ERROR_GSSCONTINUE) {
                                        /* nuke wct and bcc.  For a partial
-                                        * write, assume they're OK.
+                                        * write or an in-process authentication handshake, 
+                     * assume they're OK.
                                         */
                                        *outWctp++ = 0;
                                        *outWctp++ = 0;
@@ -4837,7 +5994,7 @@ resume:
                                break;
                        }
                        else {
-                               smb_MapCoreError(code, vcp, &errCode, &errClass);
+                smb_MapCoreError(code, vcp, &errCode, &errClass);
                                outWctp = outp->wctp;
                                smbp = (smb_t *) &outp->data;
                                if (code != CM_ERROR_PARTIALWRITE) {
@@ -4850,49 +6007,50 @@ resume:
                                }
                                smbp->errLow = (unsigned char) (errCode & 0xff);
                                smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
-                               smbp->rcls = errClass;
+                smbp->rcls = errClass;
                                break;
                        }
                }       /* error occurred */
                 
-                /* if we're here, we've finished one request.  Look to see if
+        /* if we're here, we've finished one request.  Look to see if
                 * this is a chained opcode.  If it is, setup things to process
                 * the chained request, and setup the output buffer to hold the
                 * chained response.  Start by finding the next input record.
-                 */
-                if (!(dp->flags & SMB_DISPATCHFLAG_CHAINED))
-                       break;          /* not a chained req */
-                tp = inp->wctp;                /* points to start of last request */
-                if (tp[0] < 2) break;  /* in a chained request, the first two
-                                        * parm fields are required, and are
-                                        * AndXCommand/AndXReserved and
-                                        * AndXOffset. */
-                if (tp[1] == 0xff) break;      /* no more chained opcodes */
-                inp->inCom = tp[1];
-                inp->wctp = inp->data + tp[3] + (tp[4] << 8);
-                inp->inCount++;
-                
-                /* and now append the next output request to the end of this
-                 * last request.  Begin by finding out where the last response
+         */
+        if (!(dp->flags & SMB_DISPATCHFLAG_CHAINED))
+            break;             /* not a chained req */
+        tp = inp->wctp;                /* points to start of last request */
+        /* in a chained request, the first two
+         * parm fields are required, and are
+         * AndXCommand/AndXReserved and
+         * AndXOffset. */
+        if (tp[0] < 2) break;  
+        if (tp[1] == 0xff) break;      /* no more chained opcodes */
+        inp->inCom = tp[1];
+        inp->wctp = inp->data + tp[3] + (tp[4] << 8);
+        inp->inCount++;
+
+        /* and now append the next output request to the end of this
+         * last request.  Begin by finding out where the last response
                 * ends, since that's where we'll put our new response.
-                 */
-                outWctp = outp->wctp;          /* ptr to out parameters */
-                osi_assert (outWctp[0] >= 2);  /* need this for all chained requests */
-                nparms = outWctp[0] << 1;
-                tp = outWctp + nparms + 1;     /* now points to bcc field */
-                nbytes = tp[0] + (tp[1] << 8); /* # of data bytes */
-                tp += 2 /* for the count itself */ + nbytes;
+         */
+        outWctp = outp->wctp;          /* ptr to out parameters */
+        osi_assert (outWctp[0] >= 2);  /* need this for all chained requests */
+        nparms = outWctp[0] << 1;
+        tp = outWctp + nparms + 1;     /* now points to bcc field */
+        nbytes = tp[0] + (tp[1] << 8); /* # of data bytes */
+        tp += 2 /* for the count itself */ + nbytes;
                /* tp now points to the new output record; go back and patch the
-                 * second parameter (off2) to point to the new record.
-                 */
-               temp = tp - ((char *) outp->data);
-                outWctp[3] = (unsigned char) (temp & 0xff);
-                outWctp[4] = (unsigned char) ((temp >> 8) & 0xff);
-                outWctp[2] = 0;        /* padding */
-                outWctp[1] = inp->inCom;       /* next opcode */
+         * second parameter (off2) to point to the new record.
+         */
+               temp = (unsigned int)tp - ((unsigned int) outp->data);
+        outWctp[3] = (unsigned char) (temp & 0xff);
+        outWctp[4] = (unsigned char) ((temp >> 8) & 0xff);
+        outWctp[2] = 0;        /* padding */
+        outWctp[1] = inp->inCom;       /* next opcode */
 
                /* finally, setup for the next iteration */
-                outp->wctp = tp;
+        outp->wctp = tp;
                outWctp = tp;
        }       /* while loop over all requests in the packet */
 
@@ -4908,21 +6066,30 @@ resume:
                }
        }
  
-        /* now send the output packet, and return */
-        if (!noSend)
+    /* now send the output packet, and return */
+    if (!noSend)
                smb_SendPacket(vcp, outp);
-       InterlockedDecrement(&ongoingOps);
+       thrd_Decrement(&ongoingOps);
 
        if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+        if (active_vcp) {
+            smb_ReleaseVC(active_vcp);
+            osi_Log2(smb_logp,
+                      "Replacing active_vcp %x with %x", active_vcp, vcp);
+        }
+        smb_HoldVC(vcp);
                active_vcp = vcp;
                last_msg_time = GetCurrentTime();
        }
-       else if (active_vcp == vcp)
+       else if (active_vcp == vcp) {
+        smb_ReleaseVC(active_vcp);
                active_vcp = NULL;
+    }
 
-        return;
+    return;
 }
 
+#ifndef DJGPP
 /* Wait for Netbios() calls to return, and make the results available to server
  * threads.  Note that server threads can't wait on the NCBevents array
  * themselves, because NCB events are manual-reset, and the servers would race
@@ -4930,19 +6097,53 @@ resume:
  */
 void smb_ClientWaiter(void *parmp)
 {
-       DWORD code, idx;
+       DWORD code;
+    int   idx;
 
        while (1) {
-               code = WaitForMultipleObjects(numNCBs, NCBevents,
+               code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBevents,
                                              FALSE, INFINITE);
                if (code == WAIT_OBJECT_0)
                        continue;
-               idx = code - WAIT_OBJECT_0;
 
-               ResetEvent(NCBevents[idx]);
-               SetEvent(NCBreturns[0][idx]);
+        /* error checking */
+        if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numNCBs))
+        {
+            int abandonIdx = code - WAIT_ABANDONED_0;
+            afsi_log("Error: smb_ClientWaiter event %d abandoned, errno %d\n", abandonIdx, GetLastError());
+        }
+
+        if (code == WAIT_IO_COMPLETION)
+        {
+            afsi_log("Error: smb_ClientWaiter WAIT_IO_COMPLETION\n");
+            continue;
+        }
+        
+        if (code == WAIT_TIMEOUT)
+        {
+            afsi_log("Error: smb_ClientWaiter WAIT_TIMEOUT, errno %d\n", GetLastError());
+        }
+
+        if (code == WAIT_FAILED)
+        {
+            afsi_log("Error: smb_ClientWaiter WAIT_FAILED, errno %d\n", GetLastError());
+        }
+
+        idx = code - WAIT_OBJECT_0;
+        /* check idx range! */
+        if (idx < 0 || idx > (sizeof(NCBevents) / sizeof(NCBevents[0])))
+        {
+            /* this is fatal - log as much as possible */
+            afsi_log("Fatal: NCBevents idx [ %d ] out of range.\n", idx);
+            osi_assert(0);
+        }
+        
+               thrd_ResetEvent(NCBevents[idx]);
+               thrd_SetEvent(NCBreturns[0][idx]);
        }
 }
+#endif /* !DJGPP */
 
 /*
  * Try to have one NCBRECV request waiting for every live session.  Not more
@@ -4950,37 +6151,115 @@ void smb_ClientWaiter(void *parmp)
  */
 void smb_ServerWaiter(void *parmp)
 {
-       DWORD code, idx_session, idx_NCB;
+       DWORD code;
+    int idx_session, idx_NCB;
        NCB *ncbp;
+#ifdef DJGPP
+    dos_ptr dos_ncb;
+#endif /* DJGPP */
 
        while (1) {
                /* Get a session */
-               code = WaitForMultipleObjects(numSessions, SessionEvents,
-                                             FALSE, INFINITE);
+               code = thrd_WaitForMultipleObjects_Event(numSessions, SessionEvents,
+                                                   FALSE, INFINITE);
                if (code == WAIT_OBJECT_0)
                        continue;
-               idx_session = code - WAIT_OBJECT_0;
+
+        if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numSessions))
+        {
+            int abandonIdx = code - WAIT_ABANDONED_0;
+            afsi_log("Error: smb_ServerWaiter (SessionEvents) event %d abandoned, errno %d\n", abandonIdx, GetLastError());
+        }
+       
+        if (code == WAIT_IO_COMPLETION)
+        {
+            afsi_log("Error: smb_ServerWaiter (SessionEvents) WAIT_IO_COMPLETION\n");
+            continue;
+        }
+       
+        if (code == WAIT_TIMEOUT)
+        {
+            afsi_log("Error: smb_ServerWaiter (SessionEvents) WAIT_TIMEOUT, errno %d\n", GetLastError());
+        }
+       
+        if (code == WAIT_FAILED)
+        {
+            afsi_log("Error: smb_ServerWaiter (SessionEvents) WAIT_FAILED, errno %d\n", GetLastError());
+        }
+       
+        idx_session = code - WAIT_OBJECT_0;
+
+        /* check idx range! */
+        if (idx_session < 0 || idx_session > (sizeof(SessionEvents) / sizeof(SessionEvents[0])))
+        {
+            /* this is fatal - log as much as possible */
+            afsi_log("Fatal: session idx [ %d ] out of range.\n", idx_session);
+            osi_assert(0);
+        }
 
                /* Get an NCB */
-NCBretry:
-               code = WaitForMultipleObjects(numNCBs, NCBavails,
-                                             FALSE, INFINITE);
+      NCBretry:
+               code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBavails,
+                                                   FALSE, INFINITE);
                if (code == WAIT_OBJECT_0)
                        goto NCBretry;
-               idx_NCB = code - WAIT_OBJECT_0;
+
+        /* error checking */
+        if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numNCBs))
+        {
+            int abandonIdx = code - WAIT_ABANDONED_0;
+            afsi_log("Error: smb_ClientWaiter (NCBavails) event %d abandoned, errno %d\n", abandonIdx, GetLastError());
+        }
+       
+        if (code == WAIT_IO_COMPLETION)
+        {
+            afsi_log("Error: smb_ClientWaiter (NCBavails) WAIT_IO_COMPLETION\n");
+            continue;
+        }
+       
+        if (code == WAIT_TIMEOUT)
+        {
+            afsi_log("Error: smb_ClientWaiter (NCBavails) WAIT_TIMEOUT, errno %d\n", GetLastError());
+        }
+       
+        if (code == WAIT_FAILED)
+        {
+            afsi_log("Error: smb_ClientWaiter (NCBavails) WAIT_FAILED, errno %d\n", GetLastError());
+        }
+               
+        idx_NCB = code - WAIT_OBJECT_0;
+
+        /* check idx range! */
+        if (idx_NCB < 0 || idx_NCB > (sizeof(NCBsessions) / sizeof(NCBsessions[0])))
+        {
+            /* this is fatal - log as much as possible */
+            afsi_log("Fatal: idx_NCB [ %d ] out of range.\n", idx_NCB);
+            osi_assert(0);
+        }
 
                /* Link them together */
                NCBsessions[idx_NCB] = idx_session;
 
                /* Fire it up */
                ncbp = NCBs[idx_NCB];
+#ifdef DJGPP
+        dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
                ncbp->ncb_lsn = (unsigned char) LSNs[idx_session];
                ncbp->ncb_command = NCBRECV | ASYNCH;
-               ncbp->ncb_lana_num = smb_LANadapter;
+               ncbp->ncb_lana_num = lanas[idx_session];
+#ifndef DJGPP
                ncbp->ncb_buffer = (unsigned char *) bufs[idx_NCB];
-               ncbp->ncb_length = SMB_PACKETSIZE;
                ncbp->ncb_event = NCBevents[idx_NCB];
+               ncbp->ncb_length = SMB_PACKETSIZE;
                Netbios(ncbp);
+#else /* DJGPP */
+               ncbp->ncb_buffer = bufs[idx_NCB]->dos_pkt;
+                ((smb_ncb_t*)ncbp)->orig_pkt = bufs[idx_NCB];
+               ncbp->ncb_event = NCBreturns[0][idx_NCB];
+               ncbp->ncb_length = SMB_PACKETSIZE;
+               Netbios(ncbp, dos_ncb);
+#endif /* !DJGPP */
        }
 }
 
@@ -4999,12 +6278,16 @@ void smb_Server(VOID *parmp)
        int myIdx = (int) parmp;
        NCB *ncbp;
        NCB *outncbp;
-        smb_packet_t *bufp;
+    smb_packet_t *bufp;
        smb_packet_t *outbufp;
-        DWORD code, rcode, idx_NCB, idx_session;
+    DWORD code, rcode;
+    int idx_NCB, idx_session;
        UCHAR rc;
-       smb_vc_t *vcp;
+       smb_vc_t *vcp = NULL;
        smb_t *smbp;
+#ifdef DJGPP
+    dos_ptr dos_ncb;
+#endif /* DJGPP */
 
        outncbp = GetNCB();
        outbufp = GetPacket();
@@ -5018,89 +6301,147 @@ void smb_Server(VOID *parmp)
                        if (tod > EXPIREDATE) {
                                (*smb_MBfunc)(NULL, "AFS demo expiration",
                                           "afsd dispatcher",
-                                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
-                               ExitThread(1);
+                                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND|MB_SERVICE_NOTIFICATION);
+                               trhd_Exit(1);
                        }
                }
 #endif /* !NOEXPIRE */
 
-               code = WaitForMultipleObjects(numNCBs, NCBreturns[myIdx],
-                                             FALSE, INFINITE);
-               if (code == WAIT_OBJECT_0)
+               code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
+                                                   FALSE, INFINITE);
+               if (code == WAIT_OBJECT_0) {
                        continue;
-               idx_NCB = code - WAIT_OBJECT_0;
+        }
+
+        /* error checking */
+        if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numNCBs))
+        {
+            int abandonIdx = code - WAIT_ABANDONED_0;
+            afsi_log("Error: smb_Server ( NCBreturns[%d] ) event %d abandoned, errno %d\n", myIdx, abandonIdx, GetLastError());
+        }
+       
+        if (code == WAIT_IO_COMPLETION)
+        {
+            afsi_log("Error: smb_Server ( NCBreturns[%d] ) WAIT_IO_COMPLETION\n", myIdx);
+            continue;
+        }
+       
+        if (code == WAIT_TIMEOUT)
+        {
+            afsi_log("Error: smb_Server ( NCBreturns[%d] ) WAIT_TIMEOUT, errno %d\n", myIdx, GetLastError());
+        }
+       
+        if (code == WAIT_FAILED)
+        {
+            afsi_log("Error: smb_Server ( NCBreturns[%d] ) WAIT_FAILED, errno %d\n", myIdx, GetLastError());
+        }
+
+        idx_NCB = code - WAIT_OBJECT_0;
+        
+        /* check idx range! */
+        if (idx_NCB < 0 || idx_NCB > (sizeof(NCBs) / sizeof(NCBs[0])))
+        {
+            /* this is fatal - log as much as possible */
+            afsi_log("Fatal: idx_NCB [ %d ] out of range.\n", idx_NCB);
+            osi_assert(0);
+        }
 
                ncbp = NCBs[idx_NCB];
+#ifdef DJGPP
+                dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
                idx_session = NCBsessions[idx_NCB];
                rc = ncbp->ncb_retcode;
 
                if (rc != NRC_PENDING && rc != NRC_GOODRET)
-                       osi_Log1(afsd_logp, "NCBRECV failure code %d", rc);
+                       osi_Log1(smb_logp, "NCBRECV failure code %d", rc);
 
                switch (rc) {
                        case NRC_GOODRET: break;
 
                        case NRC_PENDING:
                                /* Can this happen? Or is it just my
-                                * UNIX paranoia? */
+                                * UNIX paranoia? 
+                 */
                                continue;
 
                        case NRC_SCLOSED:
                        case NRC_SNUMOUT:
                                /* Client closed session */
+                if (reportSessionStartups) 
+                {
+                    afsi_log("session [ %d ] closed", idx_session);
+                }
                                dead_sessions[idx_session] = TRUE;
-                               vcp = smb_FindVC(ncbp->ncb_lsn, 0);
-                               /* Should also release vcp.  Also, would do
-                                * sanity check that all TID's are gone. */
-                               if (dead_vcp)
-                                       osi_Log1(afsd_logp,
-                                                "dead_vcp already set, %x",
-                                                dead_vcp);
-                               if (!dead_vcp
-                                    && !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
-                                       osi_Log2(afsd_logp,
-                                                "setting dead_vcp %x, user struct %x",
-                                                vcp, vcp->usersp);
-                                       dead_vcp = vcp;
-                                       vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
-                               }
-                               if (vcp->justLoggedOut) {
-                                       loggedOut = 1;
-                                       loggedOutTime = vcp->logoffTime;
-                                       loggedOutName =
-                                           strdup(vcp->justLoggedOut->name);
-                                       loggedOutUserp = vcp->justLoggedOut;
-                                       lock_ObtainWrite(&smb_rctLock);
-                                       loggedOutUserp->refCount++;
-                                       lock_ReleaseWrite(&smb_rctLock);
-                               }
+                if (vcp)
+                    smb_ReleaseVC(vcp);
+                               vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
+                               /* Should also release vcp.  [done] 2004-05-11 jaltman
+                 * Also, should do
+                                * sanity check that all TID's are gone. 
+                 *
+                 * TODO: check if we could use LSNs[idx_session] instead, 
+                 * also cleanup after dead vcp 
+                 */
+                if (vcp) {
+                    if (dead_vcp)
+                        osi_Log1(smb_logp,
+                                  "dead_vcp already set, %x",
+                                  dead_vcp);
+                    if (!dead_vcp && !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+                        osi_Log2(smb_logp,
+                                  "setting dead_vcp %x, user struct %x",
+                                  vcp, vcp->usersp);
+                        smb_HoldVC(vcp);
+                        dead_vcp = vcp;
+                        vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+                    }
+                    if (vcp->justLoggedOut) {
+                        loggedOut = 1;
+                        loggedOutTime = vcp->logoffTime;
+                        loggedOutName =
+                            strdup(vcp->justLoggedOut->unp->name);
+                        loggedOutUserp = vcp->justLoggedOut;
+                        lock_ObtainWrite(&smb_rctLock);
+                        loggedOutUserp->refCount++;
+                        lock_ReleaseWrite(&smb_rctLock);
+                    }
+                }
                                goto doneWithNCB;
 
                        case NRC_INCOMP:
                                /* Treat as transient error */
                                {
-                                       HANDLE h;
+#ifndef DJGPP
+                                       EVENT_HANDLE h;
                                        char *ptbuf[1];
                                        char s[100];
 
-                                       osi_Log1(smb_logp,
-                                               "dispatch smb recv failed, message incomplete, ncb_length %d",
-                                               ncbp->ncb_length);
-                                       h = RegisterEventSource(NULL,
-                                                               AFS_DAEMON_EVENT_NAME);
+                                       osi_Log1(smb_logp, "dispatch smb recv failed, message incomplete, ncb_length %d",
+                             ncbp->ncb_length);
+                                       h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
                                        sprintf(s, "SMB message incomplete, length %d",
-                                               ncbp->ncb_length);
+                            ncbp->ncb_length);
                                        ptbuf[0] = s;
                                        ReportEvent(h, EVENTLOG_WARNING_TYPE, 0,
-                                                   1001, NULL, 1,
-                                                   ncbp->ncb_length, ptbuf,
-                                                   bufp);
+                                1001, NULL, 1,
+                                ncbp->ncb_length, ptbuf,
+                                bufp);
                                        DeregisterEventSource(h);
+#else /* DJGPP */
+                                       osi_Log1(smb_logp,
+                              "dispatch smb recv failed, message incomplete, ncb_length %d",
+                              ncbp->ncb_length);
+                    osi_Log1(smb_logp,
+                              "SMB message incomplete, "
+                              "length %d", ncbp->ncb_length);
+#endif /* !DJGPP */
+
                                        /*
                                         * We used to discard the packet.
                                         * Instead, try handling it normally.
                                         *
-                                       continue;
+                     continue;
                                         */
                                        break;
                                }
@@ -5108,11 +6449,13 @@ void smb_Server(VOID *parmp)
                        default:
                                /* A weird error code.  Log it, sleep, and
                                 * continue. */
-                               if (vcp->errorCount++ > 3)
+                               if (vcp && vcp->errorCount++ > 3) {
+                    afsi_log("session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
                                        dead_sessions[idx_session] = TRUE;
+                }
                                else {
-                                       Sleep(1000);
-                                       SetEvent(SessionEvents[idx_session]);
+                                       thrd_Sleep(1000);
+                                       thrd_SetEvent(SessionEvents[idx_session]);
                                }
                                continue;
                }
@@ -5123,54 +6466,164 @@ void smb_Server(VOID *parmp)
                if (smb_concurrentCalls > smb_maxObsConcurrentCalls)
                        smb_maxObsConcurrentCalls = smb_concurrentCalls;
 
-               vcp = smb_FindVC(ncbp->ncb_lsn, 0);
+        if (vcp)
+            smb_ReleaseVC(vcp);
+               vcp = smb_FindVC(ncbp->ncb_lsn, 0, ncbp->ncb_lana_num);
+        /*
+               * If at this point vcp is NULL (implies that packet was invalid)
+               * then we are in big trouble. This means either :
+               *   a) we have the wrong NCB.
+               *   b) Netbios screwed up the call.
+               * Obviously this implies that 
+               *   ( LSNs[idx_session] != ncbp->ncb_lsn ||
+               *   lanas[idx_session] != ncbp->ncb_lana_num )
+               * Either way, we can't do anything with this packet.
+               * Log, sleep and resume.
+               */
+               if(!vcp) {
+                       HANDLE h;
+                       char buf[1000];
+                       char *ptbuf[1];
+
+                       sprintf(buf,
+                               "Bad vcp!! : "
+                               "LSNs[idx_session]=[%d],"
+                               "lanas[idx_session]=[%d],"
+                               "ncbp->ncb_lsn=[%d],"
+                               "ncbp->ncb_lana_num=[%d]",
+                               LSNs[idx_session],
+                               lanas[idx_session],
+                               ncbp->ncb_lsn,
+                               ncbp->ncb_lana_num);
+
+                       ptbuf[0] = buf;
+
+                       h = RegisterEventSource(NULL,AFS_DAEMON_EVENT_NAME);
+                       if(h) {
+                               ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1001, NULL,1,sizeof(*ncbp),ptbuf,(void*)ncbp);
+                               DeregisterEventSource(h);
+                       }
+
+                       /* Also log in the trace log. */
+                       osi_Log4(smb_logp, "Server: BAD VCP!"
+                               "LSNs[idx_session]=[%d],"
+                               "lanas[idx_session]=[%d],"
+                               "ncbp->ncb_lsn=[%d],"
+                               "ncbp->ncb_lana_num=[%d]",
+                               LSNs[idx_session],
+                               lanas[idx_session],
+                               ncbp->ncb_lsn,
+                               ncbp->ncb_lana_num);
+
+                       /* thrd_Sleep(1000); Don't bother sleeping */
+                       thrd_SetEvent(SessionEvents[idx_session]);
+                       smb_concurrentCalls--;
+                       continue;
+               }
+
+
                vcp->errorCount = 0;
                bufp = (struct smb_packet *) ncbp->ncb_buffer;
+#ifdef DJGPP
+               bufp = ((smb_ncb_t *) ncbp)->orig_pkt;
+        /* copy whole packet to virtual memory */
+        /*fprintf(stderr, "smb_Server: copying dos packet at 0x%x, "
+        "bufp=0x%x\n",
+        bufp->dos_pkt / 16, bufp);*/
+        fflush(stderr);
+        dosmemget(bufp->dos_pkt, ncbp->ncb_length, bufp->data);
+#endif /* DJGPP */
                smbp = (smb_t *)bufp->data;
                outbufp->flags = 0;
 
+#if !defined(DJGPP) && !defined(AFS_WIN32_ENV)
+        __try
+        {
+#endif
                if (smbp->com == 0x1d) {
                        /* Special handling for Write Raw */
                        raw_write_cont_t rwc;
-                       HANDLE rwevent;
-                       smb_DispatchPacket(vcp, bufp, outbufp, ncbp, &rwc);
+                       EVENT_HANDLE rwevent;
+            char eventName[MAX_PATH];
+            
+            smb_DispatchPacket(vcp, bufp, outbufp, ncbp, &rwc);
                        if (rwc.code == 0) {
-                               rwevent = CreateEvent(NULL, FALSE, FALSE, NULL);
+                               rwevent = thrd_CreateEvent(NULL, FALSE, FALSE, TEXT("smb_Server() rwevent"));
+                if ( GetLastError() == ERROR_ALREADY_EXISTS )
+                    afsi_log("Event Object Already Exists: %s", eventName);
                                ncbp->ncb_command = NCBRECV | ASYNCH;
                                ncbp->ncb_lsn = (unsigned char) vcp->lsn;
-                               ncbp->ncb_lana_num = smb_LANadapter;
+                               ncbp->ncb_lana_num = vcp->lana;
                                ncbp->ncb_buffer = rwc.buf;
                                ncbp->ncb_length = 65535;
                                ncbp->ncb_event = rwevent;
+#ifndef DJGPP
                                Netbios(ncbp);
-                               rcode = WaitForSingleObject(rwevent,
-                                                           RAWTIMEOUT);
-                               CloseHandle(rwevent);
+#else
+                               Netbios(ncbp, dos_ncb);
+#endif /* !DJGPP */
+                               rcode = thrd_WaitForSingleObject_Event(rwevent, RAWTIMEOUT);
+                               thrd_CloseHandle(rwevent);
                        }
-                       SetEvent(SessionEvents[idx_session]);
+                       thrd_SetEvent(SessionEvents[idx_session]);
                        if (rwc.code == 0)
-                               smb_CompleteWriteRaw(vcp, bufp, outbufp, ncbp,
-                                                    &rwc);
+                               smb_CompleteWriteRaw(vcp, bufp, outbufp, ncbp, &rwc);
                } else if (smbp->com == 0xa0) { 
-                        /* 
-                        * Serialize the handling for NT Transact 
-                        * (defect 11626)
-                         */
-                       smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL);
-                       SetEvent(SessionEvents[idx_session]);
-                } else {
-                       SetEvent(SessionEvents[idx_session]);
+            /* 
+             * Serialize the handling for NT Transact 
+             * (defect 11626)
+             */
+            smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL);
+                       thrd_SetEvent(SessionEvents[idx_session]);
+        } else {
+                       thrd_SetEvent(SessionEvents[idx_session]);
+            /* TODO: what else needs to be serialized? */
                        smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL);
                }
+#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
+        }
+        __except( smb_ServerExceptionFilter() ) {
+        }
+#endif
 
                smb_concurrentCalls--;
 
 doneWithNCB:
-               SetEvent(NCBavails[idx_NCB]);
+               thrd_SetEvent(NCBavails[idx_NCB]);
        }
+    if (vcp)
+        smb_ReleaseVC(vcp);
 }
 
 /*
+ * Exception filter for the server threads.  If an exception occurs in the
+ * dispatch routines, which is where exceptions are most common, then do a
+ * force trace and give control to upstream exception handlers. Useful for
+ * debugging.
+ */
+#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
+DWORD smb_ServerExceptionFilter(void) {
+       /* While this is not the best time to do a trace, if it succeeds, then
+        * we have a trace (assuming tracing was enabled). Otherwise, this should
+        * throw a second exception.
+        */
+       HANDLE h;
+       char *ptbuf[1];
+
+       ptbuf[0] = "Unhandled exception forcing trace";
+
+       h = RegisterEventSource(NULL,AFS_DAEMON_EVENT_NAME);
+       if(h) {
+               ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1001, NULL,1,0,ptbuf,NULL);
+               DeregisterEventSource(h);
+       }
+
+       afsd_ForceTrace(TRUE);
+       return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif
+
+/*
  * Create a new NCB and associated events, packet buffer, and "space" buffer.
  * If the number of server threads is M, and the number of live sessions is
  * N, then the number of NCB's in use at any time either waiting for, or
@@ -5179,13 +6632,27 @@ doneWithNCB:
 void InitNCBslot(int idx)
 {
        struct smb_packet *bufp;
-       HANDLE retHandle;
+       EVENT_HANDLE retHandle;
        int i;
+    char eventName[MAX_PATH];
+
+    osi_assert( idx < (sizeof(NCBs) / sizeof(NCBs[0])) );
 
        NCBs[idx] = GetNCB();
-       NCBavails[idx] = CreateEvent(NULL, FALSE, TRUE, NULL);
-       NCBevents[idx] = CreateEvent(NULL, TRUE, FALSE, NULL);
-       retHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
+    sprintf(eventName,"NCBavails[%d]", idx);
+       NCBavails[idx] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS )
+        afsi_log("Event Object Already Exists: %s", eventName);
+#ifndef DJGPP
+    sprintf(eventName,"NCBevents[%d]", idx);
+       NCBevents[idx] = thrd_CreateEvent(NULL, TRUE, FALSE, eventName);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS )
+        afsi_log("Event Object Already Exists: %s", eventName);
+#endif /* !DJGPP */
+    sprintf(eventName,"NCBReturns[0<=i<smb_NumServerThreads][%d]", idx);
+       retHandle = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS )
+        afsi_log("Event Object Already Exists: %s", eventName);
        for (i=0; i<smb_NumServerThreads; i++)
                NCBreturns[i][idx] = retHandle;
        bufp = GetPacket();
@@ -5197,47 +6664,110 @@ void InitNCBslot(int idx)
 void smb_Listener(void *parmp)
 {
        NCB *ncbp;
-        long code;
-        long len;
+    long code = 0;
+    long len;
        long i, j;
-        smb_vc_t *vcp;
+    smb_vc_t *vcp;
        int flags = 0;
        char rname[NCBNAMSZ+1];
        char cname[MAX_COMPUTERNAME_LENGTH+1];
        int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
+#ifdef DJGPP
+    dos_ptr dos_ncb;
+    time_t now;
+#endif /* DJGPP */
+       int lana = (int) parmp;
 
        ncbp = GetNCB();
+#ifdef DJGPP
+    dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
+
+    /* retrieve computer name */
+    GetComputerName(cname, &cnamelen);
+    _strupr(cname);
 
        while (1) {
+               memset(ncbp, 0, sizeof(NCB));
+               flags = 0;
+
 #ifndef NOEXPIRE
                /* check for demo expiration */
                {
                        unsigned long tod = time((void *) 0);
                        if (tod > EXPIREDATE) {
                                (*smb_MBfunc)(NULL, "AFS demo expiration",
-                                          "afsd listener",
-                                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
-                               ExitThread(1);
+                               "afsd listener",
+                               MB_OK|MB_ICONSTOP|MB_SETFOREGROUND|MB_SERVICE_NOTIFICATION);
+#ifndef DJGPP
+                ExitThread(1);
+#else
+                thrd_Exit(1);
+#endif
                        }
                }
 #endif /* !NOEXPIRE */
 
-               ncbp->ncb_command = NCBLISTEN;
-               ncbp->ncb_rto = 0;      /* No receive timeout */
-               ncbp->ncb_sto = 0;      /* No send timeout */
+        ncbp->ncb_command = NCBLISTEN;
+        ncbp->ncb_rto = 0;     /* No receive timeout */
+        ncbp->ncb_sto = 0;     /* No send timeout */
 
                /* pad out with spaces instead of null termination */
                len = strlen(smb_localNamep);
-               strncpy(ncbp->ncb_name, smb_localNamep, NCBNAMSZ);
-               for(i=len; i<NCBNAMSZ; i++) ncbp->ncb_name[i] = ' ';
+        strncpy(ncbp->ncb_name, smb_localNamep, NCBNAMSZ);
+        for(i=len; i<NCBNAMSZ; i++) ncbp->ncb_name[i] = ' ';
         
-               strcpy(ncbp->ncb_callname, "*");
-               for(i=1; i<NCBNAMSZ; i++) ncbp->ncb_callname[i] = ' ';
+        strcpy(ncbp->ncb_callname, "*");
+        for(i=1; i<NCBNAMSZ; i++) ncbp->ncb_callname[i] = ' ';
         
-               ncbp->ncb_lana_num = smb_LANadapter;
+               ncbp->ncb_lana_num = lana;
 
-               code = Netbios(ncbp);
-               osi_assert(code == 0);
+#ifndef DJGPP
+        code = Netbios(ncbp);
+#else /* DJGPP */
+        code = Netbios(ncbp, dos_ncb);
+#endif
+
+        if (code != 0)
+        {
+#ifndef DJGPP
+            char tbuffer[256];
+#endif
+
+            /* terminate silently if shutdown flag is set */
+               if (smbShutdownFlag == 1) {
+#ifndef DJGPP
+                           ExitThread(1);
+#else
+                               thrd_Exit(1);
+#endif
+                       }
+
+            osi_Log2(smb_logp, 
+                     "NCBLISTEN lana=%d failed with code %d",
+                     ncbp->ncb_lana_num, code);
+            osi_Log0(smb_logp, 
+                     "Client exiting due to network failure. Please restart client.\n");
+
+#ifndef DJGPP
+            sprintf(tbuffer, 
+                     "Client exiting due to network failure.  Please restart client.\n"
+                     "NCBLISTEN lana=%d failed with code %d",
+                     ncbp->ncb_lana_num, code);
+                       if (showErrors)
+                code = (*smb_MBfunc)(NULL, tbuffer, "AFS Client Service: Fatal Error",
+                                     MB_OK|MB_SERVICE_NOTIFICATION);
+            osi_assert(tbuffer);
+            ExitThread(1);
+#else
+            fprintf(stderr, "NCBLISTEN lana=%d failed with code %d\n",
+                     ncbp->ncb_lana_num, code);
+            fprintf(stderr, "\nClient exiting due to network failure "
+                     "(possibly due to power-saving mode)\n");
+            fprintf(stderr, "Please restart client.\n");
+                       afs_exit(AFS_EXITCODE_NETWORK_FAILURE);
+#endif /* !DJGPP */
+        }
 
                /* check for remote conns */
                /* first get remote name and insert null terminator */
@@ -5248,88 +6778,322 @@ void smb_Listener(void *parmp)
                                break;
                        }
                }
-               /* get local name and compare */
-               GetComputerName(cname, &cnamelen);
-               _strupr(cname);
+
+        /* compare with local name */
                if (!isGateway)
                        if (strncmp(rname, cname, NCBNAMSZ) != 0)
                                flags |= SMB_VCFLAG_REMOTECONN;
 
-               osi_Log1(afsd_logp, "New session lsn %d", ncbp->ncb_lsn);
+               osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn);
+               /* lock */
+               lock_ObtainMutex(&smb_ListenerLock);
 
                /* New generation */
                sessionGen++;
 
                /* Log session startup */
-               if (reportSessionStartups) {
+#ifdef NOTSERVICE
+        fprintf(stderr, "New session(ncb_lsn,ncb_lana_num) %d,%d starting from host "
+                               "%s\n",
+                ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
+#endif
+        afsi_log("New session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops",
+                  ncbp->ncb_lsn,ncbp->ncb_lana_num, rname, ongoingOps);
+
+        if (reportSessionStartups) {
+#ifndef DJGPP
                        HANDLE h;
                        char *ptbuf[1];
                        char s[100];
 
                        h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-                       sprintf(s, "SMB session startup, %d ongoing ops",
-                               ongoingOps);
+                       sprintf(s, "SMB session startup, %d ongoing ops", ongoingOps);
                        ptbuf[0] = s;
                        ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1004, NULL,
-                                   1, 0, ptbuf, NULL);
+                        1, 0, ptbuf, NULL);
                        DeregisterEventSource(h);
+#else /* DJGPP */
+            afsi_log("NCBLISTEN completed, call from %s",rname);
+            osi_Log1(smb_logp, "SMB session startup, %d ongoing ops",
+                     ongoingOps);
+            time(&now);
+            fprintf(stderr, "%s: New session %d starting from host %s\n",
+                    asctime(localtime(&now)), ncbp->ncb_lsn, rname);
+            fflush(stderr);
+#endif /* !DJGPP */
                }
 
-                /* now ncbp->ncb_lsn is the connection ID */
-                vcp = smb_FindVC(ncbp->ncb_lsn, SMB_FLAG_CREATE);
+        /* now ncbp->ncb_lsn is the connection ID */
+        vcp = smb_FindVC(ncbp->ncb_lsn, SMB_FLAG_CREATE, ncbp->ncb_lana_num);
                vcp->flags |= flags;
+        strcpy(vcp->rname, rname);
 
                /* Allocate slot in session arrays */
                /* Re-use dead session if possible, otherwise add one more */
-               for (i = 0; i < numSessions; i++) {
+        /* But don't look at session[0], it is reserved */
+               for (i = 1; i < numSessions; i++) {
                        if (dead_sessions[i]) {
+                afsi_log("connecting to dead session [ %d ]", i);
                                dead_sessions[i] = FALSE;
                                break;
                        }
                }
+
+        /* assert that we do not exceed the maximum number of sessions or NCBs.
+         * we should probably want to wait for a session to be freed in case
+         * we run out.
+         */
+
+        osi_assert(i < Sessionmax - 1);
+        osi_assert(numNCBs < NCBmax - 1);   /* if we pass this test we can allocate one more */
+
                LSNs[i] = ncbp->ncb_lsn;
+               lanas[i] = ncbp->ncb_lana_num;
+               
                if (i == numSessions) {
                        /* Add new NCB for new session */
+            char eventName[MAX_PATH];
+
+            osi_Log1(smb_logp, "smb_Listener creating new session %d", i);
+
                        InitNCBslot(numNCBs);
                        numNCBs++;
-                       SetEvent(NCBavails[0]);
-                       SetEvent(NCBevents[0]);
+                       thrd_SetEvent(NCBavails[0]);
+                       thrd_SetEvent(NCBevents[0]);
                        for (j = 0; j < smb_NumServerThreads; j++)
-                               SetEvent(NCBreturns[j][0]);
+                               thrd_SetEvent(NCBreturns[j][0]);
                        /* Also add new session event */
-                       SessionEvents[i] = CreateEvent(NULL, FALSE, TRUE, NULL);
+            sprintf(eventName, "SessionEvents[%d]", i);
+            SessionEvents[i] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
+            if ( GetLastError() == ERROR_ALREADY_EXISTS )
+                afsi_log("Event Object Already Exists: %s", eventName);
                        numSessions++;
-                       SetEvent(SessionEvents[0]);
+            afsi_log("increasing numNCBs [ %d ] numSessions [ %d ]", numNCBs, numSessions);
+                       thrd_SetEvent(SessionEvents[0]);
                } else {
-                       SetEvent(SessionEvents[i]);
+                       thrd_SetEvent(SessionEvents[i]);
                }
+               /* unlock */
+               lock_ReleaseMutex(&smb_ListenerLock);
 
-        }      /* dispatch while loop */
+    }  /* dispatch while loop */
+}
+
+/* initialize Netbios */
+void smb_NetbiosInit()
+{
+    NCB *ncbp;
+#ifdef DJGPP
+    dos_ptr dos_ncb;
+#endif /* DJGPP */
+    int i, lana, code, l;
+    char s[100];
+    int delname_tried=0;
+    int len;
+    int lana_found = 0;
+    OSVERSIONINFO Version;
+
+    /* AFAIK, this is the default for the ms loopback adapter.*/
+    unsigned char kWLA_MAC[6] = { 0x02, 0x00, 0x4c, 0x4f, 0x4f, 0x50 };
+    /*******************************************************************/
+
+    /* Get the version of Windows */
+    memset(&Version, 0x00, sizeof(Version));
+    Version.dwOSVersionInfoSize = sizeof(Version);
+    GetVersionEx(&Version);
+
+    /* setup the NCB system */
+    ncbp = GetNCB();
+#ifdef DJGPP
+    dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
+
+#ifndef DJGPP
+    if (smb_LANadapter == -1) {
+        ncbp->ncb_command = NCBENUM;
+        ncbp->ncb_buffer = (PUCHAR)&lana_list;
+        ncbp->ncb_length = sizeof(lana_list);
+        code = Netbios(ncbp);
+        if (code != 0) {
+            sprintf(s, "Netbios NCBENUM error code %d", code);
+            afsi_log(s);
+            osi_panic(s, __FILE__, __LINE__);
+        }
+    }
+    else {
+        lana_list.length = 1;
+        lana_list.lana[0] = smb_LANadapter;
+    }
+         
+    for (i = 0; i < lana_list.length; i++) {
+        /* reset the adaptor: in Win32, this is required for every process, and
+         * acts as an init call, not as a real hardware reset.
+         */
+        ncbp->ncb_command = NCBRESET;
+        ncbp->ncb_callname[0] = 100;
+        ncbp->ncb_callname[2] = 100;
+        ncbp->ncb_lana_num = lana_list.lana[i];
+        code = Netbios(ncbp);
+        if (code == 0) 
+            code = ncbp->ncb_retcode;
+        if (code != 0) {
+            sprintf(s, "Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code);
+            afsi_log(s);
+            lana_list.lana[i] = 255;  /* invalid lana */
+        } else {
+            sprintf(s, "Netbios NCBRESET lana %d succeeded", lana_list.lana[i]);
+            afsi_log(s);
+        }
+    }
+#else
+    /* for DJGPP, there is no NCBENUM and NCBRESET is a real reset.  so
+       we will just fake the LANA list */
+    if (smb_LANadapter == -1) {
+        for (i = 0; i < 8; i++)
+           lana_list.lana[i] = i;
+        lana_list.length = 8;
+    }
+    else {
+        lana_list.length = 1;
+        lana_list.lana[0] = smb_LANadapter;
+    }
+#endif /* !DJGPP */
+
+    /* and declare our name so we can receive connections */
+    memset(ncbp, 0, sizeof(*ncbp));
+    len=lstrlen(smb_localNamep);
+    memset(smb_sharename,' ',NCBNAMSZ);
+    memcpy(smb_sharename,smb_localNamep,len);
+    sprintf(s, "lana_list.length %d", lana_list.length);
+    afsi_log(s);
+
+    /* Keep the name so we can unregister it later */
+    for (l = 0; l < lana_list.length; l++) {
+        lana = lana_list.lana[l];
+
+        ncbp->ncb_command = NCBADDNAME;
+        ncbp->ncb_lana_num = lana;
+        memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
+#ifndef DJGPP
+        code = Netbios(ncbp);
+#else /* DJGPP */
+        code = Netbios(ncbp, dos_ncb);
+#endif /* !DJGPP */
+          
+        afsi_log("Netbios NCBADDNAME lana=%d code=%d retcode=%d complete=%d",
+                 lana, code, ncbp->ncb_retcode,ncbp->ncb_cmd_cplt);
+        {
+            char name[NCBNAMSZ+1];
+            name[NCBNAMSZ]=0;
+            memcpy(name,ncbp->ncb_name,NCBNAMSZ);
+            afsi_log("Netbios NCBADDNAME added new name >%s<",name);
+        }
+
+        if (code == 0) code = ncbp->ncb_retcode;
+        if (code == 0) {
+            afsi_log("Netbios NCBADDNAME succeeded on lana %d\n", lana);
+#ifdef DJGPP
+            /* we only use one LANA with djgpp */
+            lana_list.lana[0] = lana;
+            lana_list.length = 1;
+#endif   
+        }
+        else {
+            sprintf(s, "Netbios NCBADDNAME lana %d error code %d", lana, code);
+            afsi_log(s);
+            if (code == NRC_BRIDGE) {    /* invalid LANA num */
+                lana_list.lana[l] = 255;
+                continue;
+            }
+            else if (code == NRC_DUPNAME) {
+                afsi_log("Name already exists; try to delete it");
+                memset(ncbp, 0, sizeof(*ncbp));
+                ncbp->ncb_command = NCBDELNAME;
+                memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
+                ncbp->ncb_lana_num = lana;
+#ifndef DJGPP
+                code = Netbios(ncbp);
+#else
+                code = Netbios(ncbp, dos_ncb);
+#endif /* DJGPP */
+                if (code == 0) code = ncbp->ncb_retcode;
+                else {
+                    sprintf(s, "Netbios NCBDELNAME lana %d error code %d\n", lana, code);
+                    afsi_log(s);
+                }
+                if (code != 0 || delname_tried) {
+                    lana_list.lana[l] = 255;
+                }
+                else if (code == 0) {
+                    if (!delname_tried) {
+                        lana--;
+                        delname_tried = 1;
+                        continue;
+                    }
+                }
+            }
+            else {
+                sprintf(s, "Netbios NCBADDNAME lana %d error code %d", lana, code);
+                afsi_log(s);
+                lana_list.lana[l] = 255;  /* invalid lana */
+                osi_panic(s, __FILE__, __LINE__);
+            }
+        }
+        if (code == 0) {
+            lana_found = 1;   /* at least one worked */
+#ifdef DJGPP
+            break;
+#endif
+        }
+    }
+
+    osi_assert(lana_list.length >= 0);
+    if (!lana_found) {
+        sprintf(s, "No valid LANA numbers found!");
+        osi_panic(s, __FILE__, __LINE__);
+    }
+        
+    /* we're done with the NCB now */
+    FreeNCB(ncbp);
 }
 
 void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
-       int nThreads, void *aMBfunc)
+              int nThreads
+#ifndef DJGPP
+              , void *aMBfunc
+#endif
+  )
+
 {
-       HANDLE phandle;
-        long lpid;
-        int i;
-        long code;
-        int len;
-        NCB *ncbp;
+       thread_t phandle;
+    int lpid;
+    int i;
+    int len;
        struct tm myTime;
-       char s[100];
-
+#ifdef DJGPP
+    int npar, seg, sel;
+    dos_ptr rawBuf;
+#endif /* DJGPP */
+    EVENT_HANDLE retHandle;
+    char eventName[MAX_PATH];
+
+#ifndef DJGPP
        smb_MBfunc = aMBfunc;
+#endif /* DJGPP */
 
 #ifndef NOEXPIRE
        /* check for demo expiration */
        {
                unsigned long tod = time((void *) 0);
                if (tod > EXPIREDATE) {
-                       (*smb_MBfunc)(NULL, "AFS demo expiration",
-                                  "afsd",
-                                  MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
+#ifndef DJGPP
+                       (*smb_MBfunc)(NULL, "AFS demo expiration", "afsd",
+                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND|MB_SERVICE_NOTIFICATION);
                        exit(1);
+#else /* DJGPP */
+            fprintf(stderr, "AFS demo expiration\n");
+            afs_exit(0);
+#endif /* !DJGPP */
                }
        }
 #endif /* !NOEXPIRE */
@@ -5353,77 +7117,95 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        /* initialize the remote debugging log */
        smb_logp = logp;
         
-        /* remember the name */
+    /* remember the name */
        len = strlen(snamep);
-        smb_localNamep = malloc(len+1);
-        strcpy(smb_localNamep, snamep);
+    smb_localNamep = malloc(len+1);
+    strcpy(smb_localNamep, snamep);
+    afsi_log("smb_localNamep is >%s<", smb_localNamep);
 
        /* and the global lock */
-        lock_InitializeRWLock(&smb_globalLock, "smb global lock");
-        lock_InitializeRWLock(&smb_rctLock, "smb refct and tree struct lock");
+    lock_InitializeRWLock(&smb_globalLock, "smb global lock");
+    lock_InitializeRWLock(&smb_rctLock, "smb refct and tree struct lock");
 
        /* Raw I/O data structures */
        lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock");
 
+       lock_InitializeMutex(&smb_ListenerLock, "smb listener lock");
+       
        /* 4 Raw I/O buffers */
-       smb_RawBufs = GlobalAlloc(GMEM_FIXED, 65536);
+#ifndef DJGPP
+       smb_RawBufs = calloc(65536,1);
        *((char **)smb_RawBufs) = NULL;
        for (i=0; i<3; i++) {
-               char *rawBuf = GlobalAlloc(GMEM_FIXED, 65536);
+               char *rawBuf = calloc(65536,1);
                *((char **)rawBuf) = smb_RawBufs;
                smb_RawBufs = rawBuf;
        }
+#else /* DJGPP */
+    npar = 65536 >> 4;  /* number of paragraphs */
+    seg = __dpmi_allocate_dos_memory(npar, &smb_RawBufSel[0]);
+    if (seg == -1) {
+        afsi_log("Cannot allocate %d paragraphs of DOS memory",
+                  npar);
+        osi_panic("",__FILE__,__LINE__);
+    }
+    else {
+        afsi_log("Allocated %d paragraphs of DOS mem at 0x%X",
+                  npar, seg);
+    }
+    smb_RawBufs = (seg * 16) + 0;  /* DOS physical address */
+        
+    _farpokel(_dos_ds, smb_RawBufs, NULL);
+    for (i=0; i<SMB_RAW_BUFS-1; i++) {
+        npar = 65536 >> 4;  /* number of paragraphs */
+        seg = __dpmi_allocate_dos_memory(npar, &smb_RawBufSel[i+1]);
+        if (seg == -1) {
+            afsi_log("Cannot allocate %d paragraphs of DOS memory",
+                      npar);
+            osi_panic("",__FILE__,__LINE__);
+        }
+        else {
+            afsi_log("Allocated %d paragraphs of DOS mem at 0x%X",
+                      npar, seg);
+        }
+        rawBuf = (seg * 16) + 0;  /* DOS physical address */
+        /*_farpokel(_dos_ds, smb_RawBufs, smb_RawBufs);*/
+        _farpokel(_dos_ds, rawBuf, smb_RawBufs);
+        smb_RawBufs = rawBuf;
+    }
+#endif /* !DJGPP */
 
        /* global free lists */
        smb_ncbFreeListp = NULL;
-        smb_packetFreeListp = NULL;
-
-       /* setup the NCB system */
-       ncbp = GetNCB();
+    smb_packetFreeListp = NULL;
 
-       /* reset the adaptor: in Win32, this is required for every process, and
-         * acts as an init call, not as a real hardware reset.
-         */
-        ncbp->ncb_command = NCBRESET;
-        ncbp->ncb_callname[0] = 100;
-        ncbp->ncb_callname[2] = 100;
-       ncbp->ncb_lana_num = smb_LANadapter;
-        code = Netbios(ncbp);
-        if (code == 0) code = ncbp->ncb_retcode;
-       if (code != 0) {
-               sprintf(s, "Netbios NCBRESET error code %d", code);
-               afsi_log(s);
-               osi_panic(s, __FILE__, __LINE__);
-       }
-
-       /* and declare our name so we can receive connections */
-       memset(ncbp, 0, sizeof(*ncbp));
-       ncbp->ncb_lana_num = smb_LANadapter;
-        ncbp->ncb_command = NCBADDNAME;
-       strncpy(ncbp->ncb_name, snamep, len);
-        for(i=len; i<NCBNAMSZ; i++) ncbp->ncb_name[i] = ' ';
-        code = Netbios(ncbp);
-       if (code == 0) {
-               code = ncbp->ncb_retcode;
-       }
-       if (code != 0) {
-               afsi_log("Netbios NCBADDNAME error code %d", code);
-       }
-        
-       /* we're done with the NCB now */
-        FreeNCB(ncbp);
+    smb_NetbiosInit();
 
        /* Initialize listener and server structures */
+    numVCs = 0;
        memset(dead_sessions, 0, sizeof(dead_sessions));
-       SessionEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
+    sprintf(eventName, "SessionEvents[0]");
+       SessionEvents[0] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS )
+        afsi_log("Event Object Already Exists: %s", eventName);
        numSessions = 1;
        smb_NumServerThreads = nThreads;
-       NCBavails[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
-       NCBevents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
-       NCBreturns = malloc(nThreads * sizeof(HANDLE *));
-       for (i = 0; i < nThreads; i++) {
-               NCBreturns[i] = malloc(NCBmax * sizeof(HANDLE));
-               NCBreturns[i][0] = CreateEvent(NULL, FALSE, FALSE, NULL);
+    sprintf(eventName, "NCBavails[0]");
+       NCBavails[0] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS )
+        afsi_log("Event Object Already Exists: %s", eventName);
+    sprintf(eventName, "NCBevents[0]");
+       NCBevents[0] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS )
+        afsi_log("Event Object Already Exists: %s", eventName);
+       NCBreturns = malloc(nThreads * sizeof(EVENT_HANDLE *));
+    sprintf(eventName, "NCBreturns[0<=i<smb_NumServerThreads][0]");
+    retHandle = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS )
+        afsi_log("Event Object Already Exists: %s", eventName);
+       for (i = 0; i < smb_NumServerThreads; i++) {
+               NCBreturns[i] = malloc(NCBmax * sizeof(EVENT_HANDLE));
+               NCBreturns[i][0] = retHandle;
        }
        for (i = 1; i <= nThreads; i++)
                InitNCBslot(i);
@@ -5445,7 +7227,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        smb_dispatchTable[0x0b].procp = smb_ReceiveCoreWrite;
        smb_dispatchTable[0x0c].procp = smb_ReceiveCoreLockRecord;
        smb_dispatchTable[0x0d].procp = smb_ReceiveCoreUnlockRecord;
-       smb_dispatchTable[0x0e].procp = smb_SendCoreBadOp;
+       smb_dispatchTable[0x0e].procp = smb_SendCoreBadOp; /* create temporary */
        smb_dispatchTable[0x0f].procp = smb_ReceiveCoreCreate;
        smb_dispatchTable[0x10].procp = smb_ReceiveCoreCheckPath;
        smb_dispatchTable[0x11].procp = smb_SendCoreBadOp;      /* process exit */
@@ -5462,25 +7244,25 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        smb_dispatchTable[0x2b].procp = smb_ReceiveCoreEcho;
        /* Set NORESPONSE because smb_ReceiveCoreEcho() does the responses itself */
        smb_dispatchTable[0x2b].flags |= SMB_DISPATCHFLAG_NORESPONSE;
-        smb_dispatchTable[0x2d].procp = smb_ReceiveV3OpenX;
-        smb_dispatchTable[0x2d].flags |= SMB_DISPATCHFLAG_CHAINED;
-        smb_dispatchTable[0x2e].procp = smb_ReceiveV3ReadX;
-        smb_dispatchTable[0x2e].flags |= SMB_DISPATCHFLAG_CHAINED;
+    smb_dispatchTable[0x2d].procp = smb_ReceiveV3OpenX;
+    smb_dispatchTable[0x2d].flags |= SMB_DISPATCHFLAG_CHAINED;
+    smb_dispatchTable[0x2e].procp = smb_ReceiveV3ReadX;
+    smb_dispatchTable[0x2e].flags |= SMB_DISPATCHFLAG_CHAINED;
        smb_dispatchTable[0x32].procp = smb_ReceiveV3Tran2A;    /* both are same */
-        smb_dispatchTable[0x32].flags |= SMB_DISPATCHFLAG_NORESPONSE;
-        smb_dispatchTable[0x33].procp = smb_ReceiveV3Tran2A;
-        smb_dispatchTable[0x33].flags |= SMB_DISPATCHFLAG_NORESPONSE;
-        smb_dispatchTable[0x34].procp = smb_ReceiveV3FindClose;
-        smb_dispatchTable[0x35].procp = smb_ReceiveV3FindNotifyClose;
+    smb_dispatchTable[0x32].flags |= SMB_DISPATCHFLAG_NORESPONSE;
+    smb_dispatchTable[0x33].procp = smb_ReceiveV3Tran2A;
+    smb_dispatchTable[0x33].flags |= SMB_DISPATCHFLAG_NORESPONSE;
+    smb_dispatchTable[0x34].procp = smb_ReceiveV3FindClose;
+    smb_dispatchTable[0x35].procp = smb_ReceiveV3FindNotifyClose;
        smb_dispatchTable[0x70].procp = smb_ReceiveCoreTreeConnect;
        smb_dispatchTable[0x71].procp = smb_ReceiveCoreTreeDisconnect;
        smb_dispatchTable[0x72].procp = smb_ReceiveNegotiate;
        smb_dispatchTable[0x73].procp = smb_ReceiveV3SessionSetupX;
-        smb_dispatchTable[0x73].flags |= SMB_DISPATCHFLAG_CHAINED;
-        smb_dispatchTable[0x74].procp = smb_ReceiveV3UserLogoffX;
-        smb_dispatchTable[0x74].flags |= SMB_DISPATCHFLAG_CHAINED;
-        smb_dispatchTable[0x75].procp = smb_ReceiveV3TreeConnectX;
-        smb_dispatchTable[0x75].flags |= SMB_DISPATCHFLAG_CHAINED;
+    smb_dispatchTable[0x73].flags |= SMB_DISPATCHFLAG_CHAINED;
+    smb_dispatchTable[0x74].procp = smb_ReceiveV3UserLogoffX;
+    smb_dispatchTable[0x74].flags |= SMB_DISPATCHFLAG_CHAINED;
+    smb_dispatchTable[0x75].procp = smb_ReceiveV3TreeConnectX;
+    smb_dispatchTable[0x75].flags |= SMB_DISPATCHFLAG_CHAINED;
        smb_dispatchTable[0x80].procp = smb_ReceiveCoreGetDiskAttributes;
        smb_dispatchTable[0x81].procp = smb_ReceiveCoreSearchDir;
        smb_dispatchTable[0xA0].procp = smb_ReceiveNTTransact;
@@ -5494,7 +7276,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        smb_dispatchTable[0xc3].procp = smb_SendCoreBadOp;
        for(i=0xd0; i<= 0xd7; i++) {
                smb_dispatchTable[i].procp = smb_SendCoreBadOp;
-        }
+    }
 
        /* setup tran 2 dispatch table */
        smb_tran2DispatchTable[0].procp = smb_ReceiveTran2Open;
@@ -5514,41 +7296,301 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
 
        smb3_Init();
 
+       /* if we are doing SMB authentication we have register outselves as a logon process */
+       if (smb_authType != SMB_AUTH_NONE) {
+        NTSTATUS nts;
+               LSA_STRING afsProcessName;
+               LSA_OPERATIONAL_MODE dummy; /*junk*/
+               DWORD bufsize;
+
+               afsProcessName.Buffer = "OpenAFSClientDaemon";
+               afsProcessName.Length = strlen(afsProcessName.Buffer);
+               afsProcessName.MaximumLength = afsProcessName.Length + 1;
+
+               nts = LsaRegisterLogonProcess(&afsProcessName, &smb_lsaHandle, &dummy);
+
+               if (nts == STATUS_SUCCESS) {
+                       LSA_STRING packageName;
+                       /* we are registered. Find out the security package id */
+                       packageName.Buffer = MSV1_0_PACKAGE_NAME;
+                       packageName.Length = strlen(packageName.Buffer);
+                       packageName.MaximumLength = packageName.Length + 1;
+                       nts = LsaLookupAuthenticationPackage(smb_lsaHandle, &packageName , &smb_lsaSecPackage);
+                       if (nts == STATUS_SUCCESS) {
+                               /* Now get ourselves a domain name. */
+                               /* For now we are using the local computer name as the domain name.
+                                * It is actually the domain for local logins, and we are acting as
+                                * a local SMB server. 
+                 */
+                               bufsize = sizeof(smb_ServerDomainName) - 1;
+                               GetComputerName(smb_ServerDomainName, &bufsize);
+                               smb_ServerDomainNameLength = bufsize + 1; /* bufsize doesn't include terminator */
+                               afsi_log("Setting SMB server domain name to [%s]", smb_ServerDomainName);
+
+                               smb_lsaLogonOrigin.Buffer = "OpenAFS";
+                               smb_lsaLogonOrigin.Length = strlen(smb_lsaLogonOrigin.Buffer);
+                               smb_lsaLogonOrigin.MaximumLength = smb_lsaLogonOrigin.Length + 1;
+                       } else {
+                               afsi_log("Can't determine security package name for NTLM!! NTSTATUS=[%l]",nts);
+                       }
+               } else {
+                       afsi_log("Can't register logon process!! NTSTATUS=[%l]",nts);
+               }
+
+               if (nts != STATUS_SUCCESS) {
+                       /* something went wrong. We report the error and revert back to no authentication
+                          because we can't perform any auth requests without a successful lsa handle
+                          or sec package id. */
+                       afsi_log("Reverting to NO SMB AUTH");
+                       smb_authType = SMB_AUTH_NONE;
+               } else if ( smb_authType == SMB_AUTH_EXTENDED) {
+            /* Test to see if there is anything to negotiate.  If SPNEGO is not going to be used 
+            * then the only option is NTLMSSP anyway; so just fallback. 
+            */
+            void * secBlob;
+            int secBlobLength;
+
+            smb_NegotiateExtendedSecurity(&secBlob, &secBlobLength);
+            if (secBlobLength == 0) {
+                smb_authType = SMB_AUTH_NTLM;
+                afsi_log("Reverting to SMB AUTH NTLM");
+            } else
+                free(secBlob);
+        }
+       }
+
        /* Start listeners, waiters, servers, and daemons */
 
-        phandle = CreateThread(NULL, 65536, (LPTHREAD_START_ROUTINE) smb_Listener,
-               NULL, 0, &lpid);
-       osi_assert(phandle != NULL);
-       CloseHandle(phandle);
+       for (i = 0; i < lana_list.length; i++) {
+               if (lana_list.lana[i] == 255) continue;
+               phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Listener,
+                       (void*)lana_list.lana[i], 0, &lpid, "smb_Listener");
+               osi_assert(phandle != NULL);
+               thrd_CloseHandle(phandle);
+       }
 
-        phandle = CreateThread(NULL, 65536, (LPTHREAD_START_ROUTINE) smb_ClientWaiter,
-               NULL, 0, &lpid);
+#ifndef DJGPP
+    phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ClientWaiter,
+                          NULL, 0, &lpid, "smb_ClientWaiter");
        osi_assert(phandle != NULL);
-       CloseHandle(phandle);
+       thrd_CloseHandle(phandle);
+#endif /* !DJGPP */
 
-        phandle = CreateThread(NULL, 65536, (LPTHREAD_START_ROUTINE) smb_ServerWaiter,
-               NULL, 0, &lpid);
+    phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ServerWaiter,
+                          NULL, 0, &lpid, "smb_ServerWaiter");
        osi_assert(phandle != NULL);
-       CloseHandle(phandle);
+       thrd_CloseHandle(phandle);
 
        for (i=0; i<nThreads; i++) {
-               phandle = CreateThread(NULL, 65536,
-                                       (LPTHREAD_START_ROUTINE) smb_Server,
-                                       (void *) i, 0, &lpid);
+               phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Server,
+                              (void *) i, 0, &lpid, "smb_Server");
                osi_assert(phandle != NULL);
-               CloseHandle(phandle);
+               thrd_CloseHandle(phandle);
        }
 
-        phandle = CreateThread(NULL, 65536, (LPTHREAD_START_ROUTINE) smb_Daemon,
-               NULL, 0, &lpid);
+    phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Daemon,
+                          NULL, 0, &lpid, "smb_Daemon");
        osi_assert(phandle != NULL);
-       CloseHandle(phandle);
+       thrd_CloseHandle(phandle);
 
-       phandle = CreateThread(NULL, 65536,
-               (LPTHREAD_START_ROUTINE) smb_WaitingLocksDaemon,
-               NULL, 0, &lpid);
+       phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_WaitingLocksDaemon,
+                          NULL, 0, &lpid, "smb_WaitingLocksDaemon");
        osi_assert(phandle != NULL);
-       CloseHandle(phandle);
+       thrd_CloseHandle(phandle);
+
+#ifdef DJGPP
+        smb_ListShares();
+#endif
 
        return;
 }
+
+void smb_Shutdown(void)
+{
+    NCB *ncbp;
+#ifdef DJGPP
+    dos_ptr dos_ncb;
+#endif
+    long code = 0;
+    int i;
+
+    /*fprintf(stderr, "Entering smb_Shutdown\n");*/
+        
+    /* setup the NCB system */
+    ncbp = GetNCB();
+#ifdef DJGPP
+    dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif
+
+    /* Block new sessions by setting shutdown flag */
+    smbShutdownFlag = 1;
+
+    /* Hang up all sessions */
+    memset((char *)ncbp, 0, sizeof(NCB));
+    for (i = 1; i < numSessions; i++)
+    {
+        if (dead_sessions[i])
+            continue;
+      
+        /*fprintf(stderr, "NCBHANGUP session %d LSN %d\n", i, LSNs[i]);*/
+        ncbp->ncb_command = NCBHANGUP;
+        ncbp->ncb_lana_num = lanas[i];  /*smb_LANadapter;*/
+        ncbp->ncb_lsn = LSNs[i];
+#ifndef DJGPP
+        code = Netbios(ncbp);
+#else
+               code = Netbios(ncbp, dos_ncb);
+#endif
+        /*fprintf(stderr, "returned from NCBHANGUP session %d LSN %d\n", i, LSNs[i]);*/
+        if (code == 0) code = ncbp->ncb_retcode;
+        if (code != 0) {
+            osi_Log1(smb_logp, "Netbios NCBHANGUP error code %d", code);
+            fprintf(stderr, "Session %d Netbios NCBHANGUP error code %d", i, code);
+        }
+    }
+
+    /* Delete Netbios name */
+    memset((char *)ncbp, 0, sizeof(NCB));
+       for (i = 0; i < lana_list.length; i++) {
+               if (lana_list.lana[i] == 255) continue;
+               ncbp->ncb_command = NCBDELNAME;
+               ncbp->ncb_lana_num = lana_list.lana[i];
+               memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
+#ifndef DJGPP
+        code = Netbios(ncbp);
+#else
+               code = Netbios(ncbp, dos_ncb);
+#endif
+               if (code == 0) code = ncbp->ncb_retcode;
+               if (code != 0) {
+                       fprintf(stderr, "Netbios NCBDELNAME lana %d error code %d",
+                       ncbp->ncb_lana_num, code);
+               }
+               fflush(stderr);
+       }
+}
+
+/* Get the UNC \\<servername>\<sharename> prefix. */
+char *smb_GetSharename()
+{
+    char *name;
+
+       /* Make sure we have been properly initialized. */
+       if (smb_localNamep == NULL)
+               return NULL;
+
+    /* Allocate space for \\<servername>\<sharename>, plus the
+     * terminator.
+     */
+    name = malloc(strlen(smb_localNamep) + strlen("ALL") + 4);
+    sprintf(name, "\\\\%s\\%s", smb_localNamep, "ALL");
+    return name;
+}   
+
+#ifdef NOTSERVICE
+
+void smb_LogPacket(smb_packet_t *packet)
+{
+       BYTE *vp, *cp;
+       unsigned length, paramlen, datalen, i, j;
+       char buf[81];
+       char hex[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+
+       if(!packet) return;
+
+       osi_Log0(smb_logp, "*** SMB packet dump ***");
+
+       vp = (BYTE *) packet->data;
+
+       datalen = *((WORD*)(vp + (paramlen = ((unsigned)*(vp+20)) << 1)));
+       length = paramlen + 2 + datalen;
+
+
+       for(i=0;i < length; i+=16)
+       {
+               memset( buf, ' ', 80 );
+               buf[80] = 0;
+
+               itoa( i, buf, 16 );
+
+               buf[strlen(buf)] = ' ';
+
+               cp = (BYTE*) buf + 7;
+
+               for(j=0;j < 16 && (i+j)<length; j++)
+               {
+                       *(cp++) = hex[vp[i+j] >> 4];
+                       *(cp++) = hex[vp[i+j] & 0xf];
+                       *(cp++) = ' ';
+
+                       if(j==7)
+                       {
+                               *(cp++) = '-';
+                               *(cp++) = ' ';
+                       }
+               }
+
+               for(j=0;j < 16 && (i+j)<length;j++)
+               {
+                       *(cp++) = ( 32 <= vp[i+j] && 128 > vp[i+j] )? vp[i+j]:'.';
+                       if(j==7)
+                       {
+                               *(cp++) = ' ';
+                               *(cp++) = '-';
+                               *(cp++) = ' ';
+                       }
+               }
+
+               *cp = 0;
+
+               osi_Log0( smb_logp, buf );
+       }
+
+       osi_Log0(smb_logp, "*** End SMB packet dump ***");
+
+}
+
+#endif /* NOTSERVICE */
+
+int smb_DumpVCP(FILE *outputFile, char *cookie)
+{
+    int zilch;
+    char output[1024];
+  
+    smb_vc_t *vcp;
+  
+    lock_ObtainRead(&smb_rctLock);
+  
+    sprintf(output, "begin dumping vcpsp\n");
+    WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+
+    for(vcp = smb_allVCsp; vcp; vcp=vcp->nextp) 
+    {
+        smb_fid_t *fidp;
+      
+        sprintf(output, "%s vcp=0x%08X, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\n",
+                 cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
+        WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+      
+        sprintf(output, "begin dumping fidsp\n");
+        WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+
+        for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
+        {
+            sprintf(output, "%s -- fidp=0x%08X, refCount=%d, fid=%d, vcp=0x%08X, scp=0x%08X, ioctlp=0x%08X, NTopen_pathp=%s, NTopen_wholepathp=%s\n", 
+                     cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp, 
+                     fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL", 
+                     fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
+            WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+        }
+      
+        sprintf(output, "done dumping fidsp\n");
+        WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+    }
+
+    sprintf(output, "done dumping vcpsp\n");
+    WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+  
+    lock_ReleaseRead(&smb_rctLock);
+    return 0;
+}