dns-and-server-ref-counts-20040530
[openafs.git] / src / WINNT / afsd / cm_ioctl.c
index 92c7553..187b9cf 100644 (file)
@@ -1,16 +1,20 @@
-/* 
- * Copyright (C) 1998, 1989 Transarc Corporation - All rights reserved
- *
- * (C) COPYRIGHT IBM CORPORATION 1987, 1988
- * LICENSED MATERIALS - PROPERTY OF IBM
- *
- *
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
  */
 
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#else
+#include <sys/socket.h>
+#endif /* !DJGPP */
 #include <errno.h>
 #include <stdlib.h>
 #include <malloc.h>
 #include "afsd_init.h"
 
 #include "smb.h"
+#include "cm_server.h"
 
-#include <rxkad.h>
-
+#ifndef DJGPP
+#include <rx/rxkad.h>
 #include "afsrpc.h"
+#else
+#include <rx/rxkad.h>
+#include "afsrpc95.h"
+#endif
+
 #include "cm_rpc.h"
 
+#ifdef _DEBUG
+#include <crtdbg.h>
+#endif
+
 /* Copied from afs_tokens.h */
 #define PIOCTL_LOGON   0x1
+#define MAX_PATH 260
 
 osi_mutex_t cm_Afsdsbmt_Lock;
 
+extern afs_int32 cryptall;
+
 void cm_InitIoctl(void)
 {
        lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
@@ -97,10 +114,19 @@ void cm_ResetACLCache(cm_user_t *userp)
  */
 void TranslateExtendedChars(char *str)
 {
-        if (!str || !*str)
-                return;
-
-        CharToOem(str, str);
+#ifdef DJGPP
+    char *p;
+#endif
+
+    if (!str || !*str)
+        return;
+
+#ifndef DJGPP
+    CharToOem(str, str);
+#else
+    p = str;
+    while (*p) *p++ &= 0x7f;  /* turn off high bit; probably not right */
+#endif
 }
         
 /* parse the passed-in file name and do a namei on it.  If we fail,
@@ -154,15 +180,19 @@ void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
 void cm_NormalizeAfsPath (char *outpathp, char *inpathp)
 {
        char *cp;
-
-       if (!strnicmp (inpathp, "/afs", strlen("/afs")))
+    char bslash_mountRoot[256];
+       
+    strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
+    bslash_mountRoot[0] = '\\';
+       
+    if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
                lstrcpy (outpathp, inpathp);
-       else if (!strnicmp (inpathp, "\\afs", strlen("\\afs")))
+       else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
                lstrcpy (outpathp, inpathp);
        else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
-               sprintf (outpathp, "/afs%s", inpathp);
+               sprintf (outpathp, "%s%s", cm_mountRoot, inpathp);
        else // inpathp looks like "<cell>/usr"
-               sprintf (outpathp, "/afs/%s", inpathp);
+               sprintf (outpathp, "%s/%s", cm_mountRoot, inpathp);
 
        for (cp = outpathp; *cp != 0; ++cp) {
                if (*cp == '\\')
@@ -173,8 +203,8 @@ void cm_NormalizeAfsPath (char *outpathp, char *inpathp)
            outpathp[strlen(outpathp)-1] = 0;
        }
 
-       if (!strcmpi (outpathp, "/afs")) {
-           strcpy (outpathp, "/afs/");
+       if (!strcmpi (outpathp, cm_mountRoot)) {
+        strcpy (outpathp, cm_mountRoot);
        }
 }
 
@@ -896,12 +926,72 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
        else return CM_ERROR_NOMORETOKENS;      /* mapped to EDOM */
 }
 
+extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
+
 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
-       /* don't need to do, since NT cache manager will re-read afsdcell.ini
-         * on every access to a new cell.
-         */
-       return CM_ERROR_INVAL;
+    /* NT cache manager will read cell information from afsdcell.ini each time
+     * cell is accessed. So, this call is necessary only if list of server for a cell 
+     * changes (or IP addresses of cell servers changes).
+     * All that needs to be done is to refresh server information for all cells that 
+     * are already loaded.
+  
+     * cell list will be cm_CellLock and cm_ServerLock will be held for write.
+    */  
+  
+    cm_cell_t *cp;
+    cm_cell_t *tcp;
+  
+    cm_SkipIoctlPath(ioctlp);
+    lock_ObtainWrite(&cm_cellLock);
+  
+    for(cp = cm_allCellsp; cp; cp=cp->nextp) 
+    {
+        long code;
+      top:
+        /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
+        cm_FreeServerList(&cp->vlServersp);
+        cp->vlServersp = NULL;
+        code = cm_SearchCellFile(cp->namep, cp->namep, cm_AddCellProc, cp);
+               if (code) {
+#ifdef AFS_AFSDB_ENV
+            if (cm_dnsEnabled) {
+                int ttl;
+                code = cm_SearchCellByDNS(cp->namep, cp->namep, &ttl, cm_AddCellProc, cp);
+                if ( code ) {
+                    if ( cm_allCellsp == cp )
+                        cm_allCellsp = cp->nextp;
+                    else {
+                        for(tcp = cm_allCellsp; tcp->nextp; tcp=tcp->nextp) {
+                            if ( tcp->nextp == cp ) {
+                                tcp->nextp = cp->nextp;
+                                break;
+                            }
+                        }
+                    }   
+                    
+                    lock_FinalizeMutex(&cp->mx);
+                    free(cp->namep);
+                }
+                else {   /* got cell from DNS */
+                    cp->flags |= CM_CELLFLAG_DNS;
+                    cp->timeout = time(0) + ttl;
+                }
+            }
+#endif /* AFS_AFSDB_ENV */
+        }
+        if (code) {
+            tcp = cp;
+            cp = cp->nextp;
+            free(tcp);
+            goto top;
+        }
+        else
+            cm_RandomizeServer(&cp->vlServersp);
+    }
+    
+    lock_ReleaseWrite(&cm_cellLock);
+    return 0;       
 }
 
 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
@@ -1008,7 +1098,8 @@ long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
        vlonly     = spin->flags;
        if ( vlonly )
                type = CM_SERVER_VLDB;
-       else    type = CM_SERVER_FILE;
+       else    
+        type = CM_SERVER_FILE;
 
        for ( i=0; i < noServers; i++) 
        {
@@ -1018,7 +1109,7 @@ long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
                tmp.sin_family = AF_INET;
 
                tsp = cm_FindServer(&tmp, type);
-               if ( tsp )              /* an existing server */
+               if ( tsp )              /* an existing server - ref count increased */
                {
                        tsp->ipRank = rank; /* no need to protect by mutex*/
 
@@ -1034,13 +1125,13 @@ long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
                            /* set preferences for an existing vlserver */
                            cm_ChangeRankCellVLServer(tsp);
                        }
+            cm_PutServer(tsp);  /* decrease refcount */
                }
-               else                    /* add a new server without a cell*/
+               else    /* add a new server without a cell */
                {
-                       tsp = cm_NewServer(&tmp, type, NULL);
+                       tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
                        tsp->ipRank = rank;
                }
-               cm_PutServer(tsp);
        }
        return 0;
 }
@@ -1102,65 +1193,77 @@ long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
        char leaf[256];
-        long code;
-        cm_scache_t *dscp;
-        cm_attr_t tattr;
-        char *cp;
+    long code;
+    cm_scache_t *dscp;
+    cm_attr_t tattr;
+    char *cp;
        cm_req_t req;
-        char mpInfo[256];
-        char fullCell[256];
+    char mpInfo[256];
+    char fullCell[256];
        char volume[256];
        char cell[256];
+       int ttl;
 
        cm_InitReq(&req);
         
-        code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
-        if (code) return code;
+    code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
+    if (code) return code;
 
-        /* Translate chars for the mount point name */
-        TranslateExtendedChars(leaf);
+    /* Translate chars for the mount point name */
+    TranslateExtendedChars(leaf);
 
-        /* 
-         * The fs command allows the user to specify partial cell names on NT.  These must
-         * be expanded to the full cell name for mount points so that the mount points will
-         * work on UNIX clients.
-         */
+    /* 
+     * The fs command allows the user to specify partial cell names on NT.  These must
+     * be expanded to the full cell name for mount points so that the mount points will
+     * work on UNIX clients.
+     */
 
        /* Extract the possibly partial cell name */
        strcpy(cell, ioctlp->inDatap + 1);      /* Skip the mp type character */
         
-        if (cp = strchr(cell, ':')) {
+    if (cp = strchr(cell, ':')) {
                /* Extract the volume name */
-               *cp = 0;
+        *cp = 0;
                strcpy(volume,  cp + 1);
        
-               /* Get the full name for this cell */
-               code = cm_SearchCellFile(cell, fullCell, 0, 0);
-               if (code)
+        /* Get the full name for this cell */
+        code = cm_SearchCellFile(cell, fullCell, 0, 0);
+#ifdef AFS_AFSDB_ENV
+               if (code && cm_dnsEnabled)
+            code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
+#endif
+        if (code)
                        return CM_ERROR_NOSUCHCELL;
        
-               sprintf(mpInfo, "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
+        sprintf(mpInfo, "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
        } else {
-               /* No cell name specified */
-               strcpy(mpInfo, ioctlp->inDatap);
-        }
-
+        /* No cell name specified */
+        strcpy(mpInfo, ioctlp->inDatap);
+    }
+
+#ifdef AFS_FREELANCE_CLIENT
+       if (cm_freelanceEnabled && dscp == cm_rootSCachep) {
+         /* we are adding the mount point to the root dir., so call
+            the freelance code to do the add. */
+         code = cm_FreelanceAddMount(leaf, fullCell, volume, NULL);
+         return code;
+       }
+#endif
        /* create the symlink with mode 644.  The lack of X bits tells
-         * us that it is a mount point.
-         */
+     * us that it is a mount point.
+     */
        tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
-        tattr.unixModeBits = 0644;
+    tattr.unixModeBits = 0644;
        tattr.clientModTime = time(NULL);
 
-        code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
+    code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
        if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                smb_NotifyChange(FILE_ACTION_ADDED,
-                                FILE_NOTIFY_CHANGE_DIR_NAME,
-                                dscp, leaf, NULL, TRUE);
-
-        cm_ReleaseSCache(dscp);
+                         FILE_NOTIFY_CHANGE_DIR_NAME,
+                         dscp, leaf, NULL, TRUE);
 
-        return code;
+    cm_ReleaseSCache(dscp);
+    return code;
 }
 
 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
@@ -1237,7 +1340,8 @@ long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
        if (code == 0) {
                cp = ioctlp->outDatap;
                if (newRootScp != NULL) {
-                       strcpy(cp, "/afs/");
+            strcpy(cp, cm_mountRoot);
+            strcat(cp, "/");
                        cp += strlen(cp);
                }
                strcpy(cp, spacep->data);
@@ -1251,6 +1355,33 @@ long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
        return code;
 }
 
+long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{/*CHECK FOR VALID SYMLINK*/
+       long code;
+       cm_scache_t *dscp;
+       cm_scache_t *scp;
+       char *cp;
+       cm_req_t req;
+
+       cm_InitReq(&req);
+
+       code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
+       if (code) return code;
+
+       cp = ioctlp->inDatap;
+       osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
+
+       code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
+       cm_ReleaseSCache(dscp);
+       if (code) return code;
+
+       /* Check that it's a real symlink */
+       if (scp->fileType != CM_SCACHETYPE_SYMLINK)
+               code = CM_ERROR_INVAL;
+       cm_ReleaseSCache(scp);
+       return code;
+}
+
 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
        long code;
@@ -1321,6 +1452,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
        afs_uuid_t uuid;
        int flags;
        char sessionKey[8];
+       char *smbname;
 
        saveDataPtr = ioctlp->inDatap;
 
@@ -1365,13 +1497,26 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
                uname = tp;
                tp += strlen(tp) + 1;
 
+        if (flags & PIOCTL_LOGON) {
+                 /* SMB user name with which to associate tokens */
+                 smbname = tp;
+                 fprintf(stderr, "SMB name = %s\n", smbname);
+                 tp += strlen(tp) + 1;
+        }
+
+#ifndef DJGPP   /* for win95, session key is back in pioctl */
                /* uuid */
                memcpy(&uuid, tp, sizeof(uuid));
                if (!cm_FindTokenEvent(uuid, sessionKey))
                        return CM_ERROR_INVAL;
+#endif /* !DJGPP */
        } else
                cellp = cm_rootCellp;
 
+       if (flags & PIOCTL_LOGON) {
+          userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname);
+       }
+       
        /* store the token */
        lock_ObtainMutex(&userp->mx);
        ucellp = cm_GetUCell(userp, cellp);
@@ -1380,6 +1525,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
                free(ucellp->ticketp);  /* Discard old token if any */
        ucellp->ticketp = malloc(ticketLen);
        memcpy(ucellp->ticketp, ticket, ticketLen);
+#ifndef DJGPP
        /*
         * Get the session key from the RPC, rather than from the pioctl.
         */
@@ -1387,6 +1533,10 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
        memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
         */
        memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
+#else
+        /* for win95, we are getting the session key from the pioctl */
+        memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
+#endif /* !DJGPP */
        ucellp->kvno = ct.AuthHandle;
        ucellp->expirationTime = ct.EndTimestamp;
        ucellp->gen++;
@@ -1453,6 +1603,7 @@ long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
        /* clear token */
        ct.AuthHandle = ucellp->kvno;
+#ifndef DJGPP
        /*
         * Don't give out a real session key here
         */
@@ -1460,6 +1611,9 @@ long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
        memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
         */
        memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
+#else
+       memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
+#endif /* !DJGPP */
        ct.ViceId = 37;                 /* XXX */
        ct.BeginTimestamp = 0;          /* XXX */
        ct.EndTimestamp = ucellp->expirationTime;
@@ -1494,7 +1648,9 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
        cm_ucell_t *ucellp;
        struct ClearToken ct;
        char *tp;
+#ifndef DJGPP
        afs_uuid_t uuid;
+#endif /* !DJGPP */
 
        cm_SkipIoctlPath(ioctlp);
 
@@ -1507,8 +1663,10 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
        if (!cellp) return CM_ERROR_NOSUCHCELL;
        tp += strlen(tp) + 1;
 
+#ifndef DJGPP
        /* uuid */
        memcpy(&uuid, tp, sizeof(uuid));
+#endif /* !DJGPP */
 
        lock_ObtainMutex(&userp->mx);
 
@@ -1533,6 +1691,7 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
        /* clear token */
        ct.AuthHandle = ucellp->kvno;
+#ifndef DJGPP
        /*
         * Don't give out a real session key here
         */
@@ -1540,6 +1699,9 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
        memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
         */
        memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
+#else
+        memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
+#endif /* !DJGPP */
        ct.ViceId = 37;                 /* XXX */
        ct.BeginTimestamp = 0;          /* XXX */
        ct.EndTimestamp = ucellp->expirationTime;
@@ -1563,7 +1725,9 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
        lock_ReleaseMutex(&userp->mx);
 
+#ifndef DJGPP
        cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
+#endif /* !DJGPP */
 
        return 0;
 }
@@ -1667,7 +1831,9 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
                         * leading "/afs" when writing out the submount.
                         */
                        WritePrivateProfileString("AFS Submounts",
-                                       submountreqp, &afspath[strlen("/afs")],
+                                       submountreqp, 
+                                       (strlen(&afspath[strlen(cm_mountRoot)])) ?
+                                                 &afspath[strlen(cm_mountRoot)]:"/",
                                        "afsdsbmt.ini");
 
                        strcpy(ioctlp->outDatap, submountreqp);
@@ -1780,11 +1946,126 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
        sprintf(ioctlp->outDatap, "auto%ld", nextAutoSubmount);
 
        WritePrivateProfileString("AFS Submounts", ioctlp->outDatap,
-                                       &afspath[lstrlen("/afs")],
-                                       "afsdsbmt.ini");
+                                 (strlen(&afspath[lstrlen(cm_mountRoot)])) ? 
+                                 &afspath[lstrlen(cm_mountRoot)]:"/",
+                                 "afsdsbmt.ini");
 
        ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
        lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
        return 0;
 }
 
+long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
+{
+       memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
+        ioctlp->outDatap += sizeof(cryptall);
+
+       return 0;
+}
+
+long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
+{
+       cm_SkipIoctlPath(ioctlp);
+
+       memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
+
+       return 0;
+}
+
+#ifdef DJGPP
+extern int afsd_shutdown(int);
+extern int afs_shutdown;
+
+long cm_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp) {
+  afs_shutdown = 1;   /* flag to shut down */
+  return 0;
+}
+#endif /* DJGPP */
+
+long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
+{
+  smb_user_t *uidp = ioctlp->uidp;
+
+  if (uidp && uidp->unp) {
+    memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
+    ioctlp->outDatap += strlen(uidp->unp->name);
+       }
+
+  return 0;
+}
+
+/* 
+ * functions to dump contents of various structures. 
+ * In debug build (linked with crt debug library) will dump allocated but not freed memory
+ */
+extern int cm_DumpSCache(FILE *outputFile, char *cookie);
+extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie);
+extern int smb_DumpVCP(FILE *outputFile, char *cookie);
+
+long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{
+    long inValue = 0;
+    HANDLE hLogFile;
+    char logfileName[MAX_PATH+1];
+    char *cookie;
+  
+#ifdef _DEBUG  
+    static _CrtMemState memstate;
+#endif
+  
+    cm_SkipIoctlPath(ioctlp);
+    memcpy(&inValue, ioctlp->inDatap, sizeof(long));
+  
+    if (getenv("TEMP"))
+    {
+        strncpy(logfileName, getenv("TEMP"), MAX_PATH);
+        logfileName[MAX_PATH] = '\0';
+    }
+    else
+    {
+        GetWindowsDirectory(logfileName, sizeof(logfileName));
+    }
+    strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
+
+    hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+  
+    if (!hLogFile)
+    {
+      /* error */
+      inValue = -1;
+      memcpy(ioctlp->outDatap, &inValue, sizeof(long));
+      ioctlp->outDatap += sizeof(long);
+      
+      return 0;               
+    }
+  
+    SetFilePointer(hLogFile, 0, NULL, FILE_END);
+  
+    cookie = inValue ? "b" : "e";
+  
+#ifdef _DEBUG  
+  
+    if (inValue)
+    {
+      _CrtMemCheckpoint(&memstate);           
+    }
+    else
+    {
+        _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
+        _CrtSetReportFile(_CRT_WARN, hLogFile);
+        _CrtMemDumpAllObjectsSince(&memstate);
+    }
+#endif
+  
+    /* dump all interesting data */
+    cm_DumpSCache(hLogFile, cookie);
+    cm_DumpBufHashTable(hLogFile, cookie);
+    smb_DumpVCP(hLogFile, cookie);
+
+    CloseHandle(hLogFile);                          
+  
+    memcpy(ioctlp->outDatap, &inValue, sizeof(long));
+    ioctlp->outDatap += sizeof(long);
+  
+    return 0;
+}