2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afs/param.h>
16 #include <sys/socket.h>
28 #include "afsd_init.h"
29 #include <WINNT\afsreg.h>
32 #include "cm_server.h"
45 #include <..\afsrdr\kif.h>
51 /* Copied from afs_tokens.h */
52 #define PIOCTL_LOGON 0x1
55 osi_mutex_t cm_Afsdsbmt_Lock;
57 extern afs_int32 cryptall;
58 extern char cm_NetbiosName[];
60 extern void afsi_log(char *pattern, ...);
62 void cm_InitIoctl(void)
64 lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
67 long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
71 lock_ObtainWrite(&scp->bufCreateLock);
72 code = buf_FlushCleanPages(scp, userp, reqp);
74 lock_ObtainMutex(&scp->mx);
75 scp->cbServerp = NULL;
79 cm_FreeAllACLEnts(scp);
80 lock_ReleaseMutex(&scp->mx);
82 lock_ReleaseWrite(&scp->bufCreateLock);
83 afsi_log("cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
88 * cm_ResetACLCache -- invalidate ACL info for a user that has just
89 * obtained or lost tokens
91 void cm_ResetACLCache(cm_user_t *userp)
96 lock_ObtainWrite(&cm_scacheLock);
97 for (hash=0; hash < cm_data.hashTableSize; hash++) {
98 for (scp=cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
99 cm_HoldSCacheNoLock(scp);
100 lock_ReleaseWrite(&cm_scacheLock);
101 lock_ObtainMutex(&scp->mx);
102 cm_InvalidateACLUser(scp, userp);
103 lock_ReleaseMutex(&scp->mx);
104 lock_ObtainWrite(&cm_scacheLock);
105 cm_ReleaseSCacheNoLock(scp);
108 lock_ReleaseWrite(&cm_scacheLock);
112 * TranslateExtendedChars - This is a fix for TR 54482.
114 * If an extended character (80 - FF) is entered into a file
115 * or directory name in Windows, the character is translated
116 * into the OEM character map before being passed to us. Why
117 * this occurs is unknown. Our pioctl functions must match
118 * this translation for paths given via our own commands (like
119 * fs). If we do not do this, then we will try to perform an
120 * operation on a non-translated path, which we will fail to
121 * find, since the path was created with the translated chars.
122 * This function performs the required translation.
124 void TranslateExtendedChars(char *str)
137 while (*p) *p++ &= 0x7f; /* turn off high bit; probably not right */
141 /* parse the passed-in file name and do a namei on it. If we fail,
142 * return an error code, otherwise return the vnode located in *scpp.
144 long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
148 cm_scache_t *substRootp;
149 char * relativePath = ioctlp->inDatap, absRoot[MAX_PATH];
150 wchar_t absRoot_w[MAX_PATH];
153 osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
155 /* This is usually the file name, but for StatMountPoint it is the path. */
156 /* ioctlp->inDatap can be either of the form:
159 * \\netbios-name\submount\path\.
160 * \\netbios-name\submount\path\file
162 TranslateExtendedChars(relativePath);
165 /* we have passed the whole path, including the afs prefix.
166 when the pioctl call is made, we perform an ioctl to afsrdr
167 and it returns the correct (full) path. therefore, there is
168 no drive letter, and the path is absolute. */
169 code = cm_NameI(cm_data.rootSCachep, relativePath,
170 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
171 userp, "", reqp, scpp);
176 /* # of bytes of path */
177 code = strlen(ioctlp->inDatap) + 1;
178 ioctlp->inDatap += code;
180 /* This is usually nothing, but for StatMountPoint it is the file name. */
181 TranslateExtendedChars(ioctlp->inDatap);
186 if (relativePath[0] == relativePath[1] &&
187 relativePath[1] == '\\' &&
188 !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName)))
194 /* We may have found a UNC path.
195 * If the first component is the NetbiosName,
196 * then throw out the second component (the submount)
197 * since it had better expand into the value of ioctl->tidPathp
200 p = relativePath + 2 + strlen(cm_NetbiosName) + 1; /* buffer overflow vuln.? */
201 if ( !_strnicmp("all", p, 3) )
204 for (i = 0; *p && *p != '\\'; i++,p++ ) {
207 p++; /* skip past trailing slash */
208 shareName[i] = 0; /* terminate string */
210 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
212 /* we found a sharename, therefore use the resulting path */
213 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
214 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
215 userp, sharePath, reqp, &substRootp);
220 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
221 userp, NULL, reqp, scpp);
225 /* otherwise, treat the name as a cellname mounted off the afs root.
226 * This requires that we reconstruct the shareName string with
227 * leading and trailing slashes.
229 p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
230 if ( !_strnicmp("all", p, 3) )
234 for (i = 1; *p && *p != '\\'; i++,p++ ) {
237 p++; /* skip past trailing slash */
238 shareName[i++] = '/'; /* add trailing slash */
239 shareName[i] = 0; /* terminate string */
242 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
243 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
244 userp, shareName, reqp, &substRootp);
248 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
249 userp, NULL, reqp, scpp);
254 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
255 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
256 userp, ioctlp->tidPathp, reqp, &substRootp);
260 code = cm_NameI(substRootp, relativePath, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
261 userp, NULL, reqp, scpp);
266 /* # of bytes of path */
267 code = strlen(ioctlp->inDatap) + 1;
268 ioctlp->inDatap += code;
270 /* This is usually nothing, but for StatMountPoint it is the file name. */
271 TranslateExtendedChars(ioctlp->inDatap);
273 /* and return success */
277 void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
281 temp = strlen(ioctlp->inDatap) + 1;
282 ioctlp->inDatap += temp;
286 /* format the specified path to look like "/afs/<cellname>/usr", by
287 * adding "/afs" (if necessary) in front, changing any \'s to /'s, and
288 * removing any trailing "/"'s. One weirdo caveat: "/afs" will be
289 * intentionally returned as "/afs/"--this makes submount manipulation
290 * easier (because we can always jump past the initial "/afs" to find
291 * the AFS path that should be written into afsdsbmt.ini).
293 void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp)
296 char bslash_mountRoot[256];
298 strncpy(bslash_mountRoot, cm_mountRoot, sizeof(bslash_mountRoot) - 1);
299 bslash_mountRoot[0] = '\\';
301 if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
302 StringCbCopy(outpathp, outlen, inpathp);
303 else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
304 StringCbCopy(outpathp, outlen, inpathp);
305 else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
306 StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
307 else // inpathp looks like "<cell>/usr"
308 StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
310 for (cp = outpathp; *cp != 0; ++cp) {
315 if (strlen(outpathp) && (outpathp[strlen(outpathp)-1] == '/')) {
316 outpathp[strlen(outpathp)-1] = 0;
319 if (!strcmpi (outpathp, cm_mountRoot)) {
320 StringCbCopy(outpathp, outlen, cm_mountRoot);
324 #define LEAF_SIZE 256
325 /* parse the passed-in file name and do a namei on its parent. If we fail,
326 * return an error code, otherwise return the vnode located in *scpp.
328 long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
329 cm_scache_t **scpp, char *leafp)
334 cm_scache_t *substRootp;
336 StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap);
337 tp = strrchr(tbuffer, '\\');
338 jp = strrchr(tbuffer, '/');
341 else if (jp && (tp - tbuffer) < (jp - tbuffer))
344 StringCbCopyA(tbuffer, sizeof(tbuffer), "\\");
346 StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap);
351 StringCbCopyA(leafp, LEAF_SIZE, tp+1);
354 if (tbuffer[0] == tbuffer[1] &&
355 tbuffer[1] == '\\' &&
356 !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName)))
362 /* We may have found a UNC path.
363 * If the first component is the NetbiosName,
364 * then throw out the second component (the submount)
365 * since it had better expand into the value of ioctl->tidPathp
368 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
369 if ( !_strnicmp("all", p, 3) )
372 for (i = 0; *p && *p != '\\'; i++,p++ ) {
375 p++; /* skip past trailing slash */
376 shareName[i] = 0; /* terminate string */
378 shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
380 /* we found a sharename, therefore use the resulting path */
381 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
382 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
383 userp, sharePath, reqp, &substRootp);
385 if (code) return code;
387 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
388 userp, NULL, reqp, scpp);
389 if (code) return code;
391 /* otherwise, treat the name as a cellname mounted off the afs root.
392 * This requires that we reconstruct the shareName string with
393 * leading and trailing slashes.
395 p = tbuffer + 2 + strlen(cm_NetbiosName) + 1;
396 if ( !_strnicmp("all", p, 3) )
400 for (i = 1; *p && *p != '\\'; i++,p++ ) {
403 p++; /* skip past trailing slash */
404 shareName[i++] = '/'; /* add trailing slash */
405 shareName[i] = 0; /* terminate string */
407 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
408 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
409 userp, shareName, reqp, &substRootp);
410 if (code) return code;
412 code = cm_NameI(substRootp, p, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
413 userp, NULL, reqp, scpp);
414 if (code) return code;
417 code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
418 CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
419 userp, ioctlp->tidPathp, reqp, &substRootp);
420 if (code) return code;
422 code = cm_NameI(substRootp, tbuffer, CM_FLAG_FOLLOW,
423 userp, NULL, reqp, scpp);
424 if (code) return code;
427 /* # of bytes of path */
428 code = strlen(ioctlp->inDatap) + 1;
429 ioctlp->inDatap += code;
431 /* and return success */
435 long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
440 AFSFetchStatus fileStatus;
446 struct rx_connection * callp;
450 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
451 if (code) return code;
453 /* now make the get acl call */
454 fid.Volume = scp->fid.volume;
455 fid.Vnode = scp->fid.vnode;
456 fid.Unique = scp->fid.unique;
458 acl.AFSOpaque_val = ioctlp->outDatap;
459 acl.AFSOpaque_len = 0;
460 code = cm_Conn(&scp->fid, userp, &req, &connp);
463 callp = cm_GetRxConn(connp);
464 code = RXAFS_FetchACL(callp, &fid, &acl, &fileStatus, &volSync);
465 rx_PutConnection(callp);
467 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
468 code = cm_MapRPCError(code, &req);
469 cm_ReleaseSCache(scp);
471 if (code) return code;
473 /* skip over return data */
474 tlen = strlen(ioctlp->outDatap) + 1;
475 ioctlp->outDatap += tlen;
477 /* and return success */
481 long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
490 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
491 if (code) return code;
493 #ifdef AFS_FREELANCE_CLIENT
494 if ( cm_freelanceEnabled &&
495 scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
496 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
497 scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) {
498 StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root");
499 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
502 #endif /* AFS_FREELANCE_CLIENT */
504 cellp = cm_FindCellByID(scp->fid.cell);
506 StringCbCopyA(ioctlp->outDatap, 999999, cellp->name);
507 ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
511 code = CM_ERROR_NOSUCHCELL;
514 cm_ReleaseSCache(scp);
518 long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
523 AFSFetchStatus fileStatus;
528 struct rx_connection * callp;
532 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
533 if (code) return code;
535 /* now make the get acl call */
536 fid.Volume = scp->fid.volume;
537 fid.Vnode = scp->fid.vnode;
538 fid.Unique = scp->fid.unique;
540 acl.AFSOpaque_val = ioctlp->inDatap;
541 acl.AFSOpaque_len = strlen(ioctlp->inDatap)+1;
542 code = cm_Conn(&scp->fid, userp, &req, &connp);
545 callp = cm_GetRxConn(connp);
546 code = RXAFS_StoreACL(callp, &fid, &acl, &fileStatus, &volSync);
547 rx_PutConnection(callp);
549 } while (cm_Analyze(connp, userp, &req, &scp->fid, &volSync, NULL, NULL, code));
550 code = cm_MapRPCError(code, &req);
552 /* invalidate cache info, since we just trashed the ACL cache */
553 lock_ObtainMutex(&scp->mx);
554 cm_DiscardSCache(scp);
555 lock_ReleaseMutex(&scp->mx);
557 cm_ReleaseSCache(scp);
562 long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
566 unsigned long volume;
572 lock_ObtainWrite(&cm_scacheLock);
573 for (i=0; i<cm_data.hashTableSize; i++) {
574 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
575 cm_HoldSCacheNoLock(scp);
576 lock_ReleaseWrite(&cm_scacheLock);
578 /* now flush the file */
579 code = cm_FlushFile(scp, userp, &req);
580 lock_ObtainWrite(&cm_scacheLock);
581 cm_ReleaseSCacheNoLock(scp);
584 lock_ReleaseWrite(&cm_scacheLock);
589 long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
593 unsigned long volume;
599 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
600 if (code) return code;
602 volume = scp->fid.volume;
603 cm_ReleaseSCache(scp);
605 lock_ObtainWrite(&cm_scacheLock);
606 for (i=0; i<cm_data.hashTableSize; i++) {
607 for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
608 if (scp->fid.volume == volume) {
609 cm_HoldSCacheNoLock(scp);
610 lock_ReleaseWrite(&cm_scacheLock);
612 /* now flush the file */
613 code = cm_FlushFile(scp, userp, &req);
614 lock_ObtainWrite(&cm_scacheLock);
615 cm_ReleaseSCacheNoLock(scp);
619 lock_ReleaseWrite(&cm_scacheLock);
624 long cm_IoctlFlushFile(struct smb_ioctl *ioctlp, struct cm_user *userp)
632 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
633 if (code) return code;
635 cm_FlushFile(scp, userp, &req);
636 cm_ReleaseSCache(scp);
641 long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
645 char offLineMsg[256];
649 AFSFetchVolumeStatus volStat;
650 AFSStoreVolumeStatus storeStat;
655 struct rx_connection * callp;
659 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
660 if (code) return code;
662 cellp = cm_FindCellByID(scp->fid.cell);
665 if (scp->flags & CM_SCACHEFLAG_RO) {
666 cm_ReleaseSCache(scp);
667 return CM_ERROR_READONLY;
670 code = cm_GetVolumeByID(cellp, scp->fid.volume, userp, &req, &tvp);
672 cm_ReleaseSCache(scp);
676 /* Copy the junk out, using cp as a roving pointer. */
677 cp = ioctlp->inDatap;
678 memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
679 cp += sizeof(AFSFetchVolumeStatus);
680 StringCbCopyA(volName, sizeof(volName), cp);
681 cp += strlen(volName)+1;
682 StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
683 cp += strlen(offLineMsg)+1;
684 StringCbCopyA(motd, sizeof(motd), cp);
686 if (volStat.MinQuota != -1) {
687 storeStat.MinQuota = volStat.MinQuota;
688 storeStat.Mask |= AFS_SETMINQUOTA;
690 if (volStat.MaxQuota != -1) {
691 storeStat.MaxQuota = volStat.MaxQuota;
692 storeStat.Mask |= AFS_SETMAXQUOTA;
696 code = cm_Conn(&scp->fid, userp, &req, &tcp);
699 callp = cm_GetRxConn(tcp);
700 code = RXAFS_SetVolumeStatus(callp, scp->fid.volume,
701 &storeStat, volName, offLineMsg, motd);
702 rx_PutConnection(callp);
704 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
705 code = cm_MapRPCError(code, &req);
707 /* return on failure */
708 cm_ReleaseSCache(scp);
713 /* we are sending parms back to make compat. with prev system. should
714 * change interface later to not ask for current status, just set
717 cp = ioctlp->outDatap;
718 memcpy(cp, (char *)&volStat, sizeof(VolumeStatus));
719 cp += sizeof(VolumeStatus);
720 StringCbCopyA(cp, 999999, volName);
721 cp += strlen(volName)+1;
722 StringCbCopyA(cp, 999999, offLineMsg);
723 cp += strlen(offLineMsg)+1;
724 StringCbCopyA(cp, 999999, motd);
725 cp += strlen(motd)+1;
727 /* now return updated return data pointer */
728 ioctlp->outDatap = cp;
733 long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
737 char offLineMsg[256];
741 AFSFetchVolumeStatus volStat;
747 struct rx_connection * callp;
751 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
752 if (code) return code;
755 OfflineMsg = offLineMsg;
758 code = cm_Conn(&scp->fid, userp, &req, &tcp);
761 callp = cm_GetRxConn(tcp);
762 code = RXAFS_GetVolumeStatus(callp, scp->fid.volume,
763 &volStat, &Name, &OfflineMsg, &MOTD);
764 rx_PutConnection(callp);
766 } while (cm_Analyze(tcp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
767 code = cm_MapRPCError(code, &req);
769 cm_ReleaseSCache(scp);
770 if (code) return code;
772 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
773 cp = ioctlp->outDatap;
774 memcpy(cp, (char *)&volStat, sizeof(AFSFetchVolumeStatus));
775 cp += sizeof(AFSFetchVolumeStatus);
776 StringCbCopyA(cp, 999999, volName);
777 cp += strlen(volName)+1;
778 StringCbCopyA(cp, 999999, offLineMsg);
779 cp += strlen(offLineMsg)+1;
780 StringCbCopyA(cp, 999999, motd);
781 cp += strlen(motd)+1;
783 /* return new size */
784 ioctlp->outDatap = cp;
789 long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
795 cm_serverRef_t **tsrpp, *current;
797 unsigned long volume;
803 code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
804 if (code) return code;
806 volume = scp->fid.volume;
808 cellp = cm_FindCellByID(scp->fid.cell);
811 cm_ReleaseSCache(scp);
813 code = cm_GetVolumeByID(cellp, volume, userp, &req, &tvp);
814 if (code) return code;
816 cp = ioctlp->outDatap;
818 lock_ObtainMutex(&tvp->mx);
819 tsrpp = cm_GetVolServers(tvp, volume);
820 lock_ObtainRead(&cm_serverLock);
821 for (current = *tsrpp; current; current = current->next) {
822 tsp = current->server;
823 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
826 lock_ReleaseRead(&cm_serverLock);
827 cm_FreeServerList(tsrpp);
828 lock_ReleaseMutex(&tvp->mx);
830 /* still room for terminating NULL, add it on */
831 volume = 0; /* reuse vbl */
832 memcpy(cp, (char *)&volume, sizeof(long));
835 ioctlp->outDatap = cp;
840 long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
850 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
851 if (code) return code;
853 cp = ioctlp->inDatap;
855 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
856 cm_ReleaseSCache(dscp);
857 if (code) return code;
859 lock_ObtainMutex(&scp->mx);
861 /* now check that this is a real mount point */
862 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
863 lock_ReleaseMutex(&scp->mx);
864 cm_ReleaseSCache(scp);
865 return CM_ERROR_INVAL;
868 code = cm_ReadMountPoint(scp, userp, &req);
870 cp = ioctlp->outDatap;
871 StringCbCopyA(cp, 999999, scp->mountPointStringp);
872 cp += strlen(cp) + 1;
873 ioctlp->outDatap = cp;
875 lock_ReleaseMutex(&scp->mx);
876 cm_ReleaseSCache(scp);
881 long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
891 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
892 if (code) return code;
894 cp = ioctlp->inDatap;
896 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
898 /* if something went wrong, bail out now */
903 lock_ObtainMutex(&scp->mx);
904 code = cm_SyncOp(scp, NULL, userp, &req, 0,
905 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
907 lock_ReleaseMutex(&scp->mx);
908 cm_ReleaseSCache(scp);
912 /* now check that this is a real mount point */
913 if (scp->fileType != CM_SCACHETYPE_MOUNTPOINT) {
914 lock_ReleaseMutex(&scp->mx);
915 cm_ReleaseSCache(scp);
916 code = CM_ERROR_INVAL;
920 /* time to make the RPC, so drop the lock */
921 lock_ReleaseMutex(&scp->mx);
922 cm_ReleaseSCache(scp);
924 /* easier to do it this way */
925 code = cm_Unlink(dscp, cp, userp, &req);
926 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
927 smb_NotifyChange(FILE_ACTION_REMOVED,
928 FILE_NOTIFY_CHANGE_DIR_NAME,
929 dscp, cp, NULL, TRUE);
932 cm_ReleaseSCache(dscp);
936 long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
946 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
947 tp = ioctlp->inDatap;
950 memcpy(&temp, tp, sizeof(temp));
951 if (temp == 0x12345678) { /* For afs3.3 version */
952 memcpy(&csi, tp, sizeof(csi));
953 if (csi.tinterval >= 0) {
954 cp = ioctlp->outDatap;
955 memcpy(cp, (char *)&cm_daemonCheckInterval, sizeof(long));
956 ioctlp->outDatap += sizeof(long);
957 if (csi.tinterval > 0) {
958 if (!smb_SUser(userp))
959 return CM_ERROR_NOACCESS;
960 cm_daemonCheckInterval = csi.tinterval;
968 } else { /* For pre afs3.3 versions */
969 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
970 ioctlp->inDatap = cp = ioctlp->inDatap + sizeof(long);
971 if (cp - ioctlp->inAllocp < ioctlp->inCopied) /* still more data available */
976 * 1: fast check, don't contact servers.
977 * 2: local cell only.
980 /* have cell name, too */
981 cellp = cm_GetCell(cp, 0);
982 if (!cellp) return CM_ERROR_NOSUCHCELL;
984 else cellp = (cm_cell_t *) 0;
985 if (!cellp && (temp & 2)) {
987 cellp = cm_FindCellByID(1);
989 if (!(temp & 1)) { /* if not fast, call server checker routine */
990 /* check down servers */
991 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS | CM_FLAG_CHECKUPSERVERS,
995 /* now return the current down server list */
996 cp = ioctlp->outDatap;
997 lock_ObtainRead(&cm_serverLock);
998 for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
999 if (cellp && tsp->cellp != cellp) continue; /* cell spec'd and wrong */
1000 if ((tsp->flags & CM_SERVERFLAG_DOWN)
1001 && tsp->type == CM_SERVER_FILE) {
1002 memcpy(cp, (char *)&tsp->addr.sin_addr.s_addr, sizeof(long));
1006 lock_ReleaseRead(&cm_serverLock);
1008 ioctlp->outDatap = cp;
1012 long cm_IoctlGag(struct smb_ioctl *ioctlp, struct cm_user *userp)
1014 /* we don't print anything superfluous, so we don't support the gag call */
1015 return CM_ERROR_INVAL;
1018 long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
1024 long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
1029 cm_SkipIoctlPath(ioctlp);
1031 memcpy(&temp, ioctlp->inDatap, sizeof(temp));
1033 temp = cm_data.buf_nOrigBuffers;
1035 /* temp is in 1K units, convert to # of buffers */
1036 temp = temp / (cm_data.buf_blockSize / 1024);
1039 /* now adjust the cache size */
1040 code = buf_SetNBuffers(temp);
1045 long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
1049 cm_SkipIoctlPath(ioctlp);
1051 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
1055 afsd_ForceTrace(FALSE);
1056 buf_ForceTrace(FALSE);
1060 /* set tracing value to low order bit */
1061 if ((inValue & 1) == 0) {
1062 /* disable tracing */
1063 osi_LogDisable(afsd_logp);
1066 /* enable tracing */
1067 osi_LogEnable(afsd_logp);
1071 /* see if we're supposed to do a reset, too */
1073 osi_LogReset(afsd_logp);
1076 /* and copy out tracing flag */
1077 inValue = afsd_logp->enabled; /* use as a temp vbl */
1078 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
1079 ioctlp->outDatap += sizeof(long);
1083 long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
1085 cm_cacheParms_t parms;
1087 memset(&parms, 0, sizeof(parms));
1089 /* first we get, in 1K units, the cache size */
1090 parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
1092 /* and then the actual # of buffers in use (not in the free list, I guess,
1093 * will be what we do).
1095 parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
1097 memcpy(ioctlp->outDatap, &parms, sizeof(parms));
1098 ioctlp->outDatap += sizeof(parms);
1103 long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1108 cm_serverRef_t *serverRefp;
1109 cm_server_t *serverp;
1115 cm_SkipIoctlPath(ioctlp);
1117 tp = ioctlp->inDatap;
1119 memcpy((char *)&whichCell, tp, sizeof(long));
1122 /* see if more than one long passed in, ignoring the null pathname (the -1) */
1123 if (ioctlp->inCopied-1 > sizeof(long)) {
1124 memcpy((char *)&magic, tp, sizeof(long));
1127 lock_ObtainRead(&cm_cellLock);
1128 for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->nextp) {
1129 if (whichCell == 0) break;
1132 lock_ReleaseRead(&cm_cellLock);
1136 cp = ioctlp->outDatap;
1138 if (magic == 0x12345678) {
1139 memcpy(cp, (char *)&magic, sizeof(long));
1142 memset(cp, 0, max * sizeof(long));
1144 lock_ObtainRead(&cm_serverLock); /* for going down server list */
1145 /* jaltman - do the reference counts to serverRefp contents need to be increased? */
1146 serverRefp = tcellp->vlServersp;
1147 for (i=0; i<max; i++) {
1148 if (!serverRefp) break;
1149 serverp = serverRefp->server;
1150 memcpy(cp, &serverp->addr.sin_addr.s_addr, sizeof(long));
1152 serverRefp = serverRefp->next;
1154 lock_ReleaseRead(&cm_serverLock);
1155 cp = basep + max * sizeof(afs_int32);
1156 StringCbCopyA(cp, 999999, tcellp->name);
1157 cp += strlen(tcellp->name)+1;
1158 ioctlp->outDatap = cp;
1164 return CM_ERROR_NOMORETOKENS; /* mapped to EDOM */
1167 extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
1169 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
1171 /* NT cache manager will read cell information from CellServDB each time
1172 * cell is accessed. So, this call is necessary only if list of server for a cell
1173 * changes (or IP addresses of cell servers changes).
1174 * All that needs to be done is to refresh server information for all cells that
1175 * are already loaded.
1177 * cell list will be cm_CellLock and cm_ServerLock will be held for write.
1182 cm_SkipIoctlPath(ioctlp);
1183 lock_ObtainWrite(&cm_cellLock);
1185 for (cp = cm_data.allCellsp; cp; cp=cp->nextp)
1188 /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
1189 cm_FreeServerList(&cp->vlServersp);
1190 cp->vlServersp = NULL;
1191 code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, cp);
1192 #ifdef AFS_AFSDB_ENV
1194 if (cm_dnsEnabled) {
1196 code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, cp);
1197 if ( code == 0 ) { /* got cell from DNS */
1198 cp->flags |= CM_CELLFLAG_DNS;
1199 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1200 cp->timeout = time(0) + ttl;
1205 cp->flags &= ~CM_CELLFLAG_DNS;
1207 #endif /* AFS_AFSDB_ENV */
1209 cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
1212 cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
1213 cm_RandomizeServer(&cp->vlServersp);
1217 lock_ReleaseWrite(&cm_cellLock);
1221 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
1225 if (cm_freelanceEnabled) {
1226 if (cm_GetRootCellName(ioctlp->outDatap))
1227 StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root");
1228 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1229 } else if (cm_data.rootCellp) {
1230 /* return the default cellname to the caller */
1231 StringCbCopyA(ioctlp->outDatap, 999999, cm_data.rootCellp->name);
1232 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
1234 /* if we don't know our default cell, return failure */
1235 code = CM_ERROR_NOSUCHCELL;
1241 long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
1243 long setSysName, foundname = 0;
1244 char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
1245 int t, count, num = 0;
1246 char **sysnamelist[MAXSYSNAME];
1248 cm_SkipIoctlPath(ioctlp);
1250 memcpy(&setSysName, ioctlp->inDatap, sizeof(long));
1251 ioctlp->inDatap += sizeof(long);
1255 if ( setSysName < 0 || setSysName > MAXNUMSYSNAMES )
1257 cp2 = ioctlp->inDatap;
1258 for ( cp=ioctlp->inDatap, count = 0; count < setSysName; count++ ) {
1259 /* won't go past end of ioctlp->inDatap since maxsysname*num < ioctlp->inDatap length */
1261 if (t >= MAXSYSNAME || t <= 0)
1263 /* check for names that can shoot us in the foot */
1264 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
1270 /* inname gets first entry in case we're being a translator */
1271 /* (we are never a translator) */
1272 t = strlen(ioctlp->inDatap);
1273 memcpy(inname, ioctlp->inDatap, t + 1);
1274 ioctlp->inDatap += t + 1;
1278 /* Not xlating, so local case */
1280 osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
1282 if (!setSysName) { /* user just wants the info */
1283 StringCbCopyA(outname, sizeof(outname), cm_sysName);
1284 foundname = cm_sysNameCount;
1285 *sysnamelist = cm_sysNameList;
1287 /* Local guy; only root can change sysname */
1288 /* clear @sys entries from the dnlc, once afs_lookup can
1289 * do lookups of @sys entries and thinks it can trust them */
1290 /* privs ok, store the entry, ... */
1291 StringCbCopyA(cm_sysName, sizeof(cm_sysName), inname);
1292 StringCbCopyA(cm_sysNameList[0], MAXSYSNAME, inname);
1293 if (setSysName > 1) { /* ... or list */
1294 cp = ioctlp->inDatap;
1295 for (count = 1; count < setSysName; ++count) {
1296 if (!cm_sysNameList[count])
1297 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
1298 __FILE__, __LINE__);
1300 StringCbCopyA(cm_sysNameList[count], MAXSYSNAME, cp);
1304 cm_sysNameCount = setSysName;
1308 /* return the sysname to the caller */
1309 cp = ioctlp->outDatap;
1310 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
1311 cp += sizeof(afs_int32); /* skip found flag */
1313 StringCbCopyA(cp, 999999, outname);
1314 cp += strlen(outname) + 1; /* skip name and terminating null char */
1315 for ( count=1; count < foundname ; ++count) { /* ... or list */
1316 if ( !(*sysnamelist)[count] )
1317 osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n",
1318 __FILE__, __LINE__);
1319 t = strlen((*sysnamelist)[count]);
1320 if (t >= MAXSYSNAME)
1321 osi_panic("cm_IoctlSysName: sysname entry garbled\n",
1322 __FILE__, __LINE__);
1323 StringCbCopyA(cp, 999999, (*sysnamelist)[count]);
1327 ioctlp->outDatap = cp;
1334 long cm_IoctlGetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1339 cm_SkipIoctlPath(ioctlp);
1341 cellp = cm_GetCell(ioctlp->inDatap, 0);
1343 return CM_ERROR_NOSUCHCELL;
1346 lock_ObtainMutex(&cellp->mx);
1347 if (cellp->flags & CM_CELLFLAG_SUID)
1348 temp |= CM_SETCELLFLAG_SUID;
1349 lock_ReleaseMutex(&cellp->mx);
1351 /* now copy out parm */
1352 memcpy(ioctlp->outDatap, &temp, sizeof(long));
1353 ioctlp->outDatap += sizeof(long);
1358 long cm_IoctlSetCellStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
1363 cm_SkipIoctlPath(ioctlp);
1365 cellp = cm_GetCell(ioctlp->inDatap + 2*sizeof(long), 0);
1367 return CM_ERROR_NOSUCHCELL;
1369 memcpy((char *)&temp, ioctlp->inDatap, sizeof(long));
1371 lock_ObtainMutex(&cellp->mx);
1372 if (temp & CM_SETCELLFLAG_SUID)
1373 cellp->flags |= CM_CELLFLAG_SUID;
1375 cellp->flags &= ~CM_CELLFLAG_SUID;
1376 lock_ReleaseMutex(&cellp->mx);
1381 long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1383 cm_SSetPref_t *spin; /* input */
1384 cm_SPref_t *srvin; /* one input component */
1386 int i, vlonly, noServers, type;
1387 struct sockaddr_in tmp;
1388 unsigned short rank;
1390 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1392 spin = (cm_SSetPref_t *)ioctlp->inDatap;
1393 noServers = spin->num_servers;
1394 vlonly = spin->flags;
1396 type = CM_SERVER_VLDB;
1398 type = CM_SERVER_FILE;
1400 for ( i=0; i < noServers; i++)
1402 srvin = &(spin->servers[i]);
1403 rank = srvin->rank + (rand() & 0x000f);
1404 tmp.sin_addr = srvin->host;
1405 tmp.sin_family = AF_INET;
1407 tsp = cm_FindServer(&tmp, type);
1408 if ( tsp ) /* an existing server - ref count increased */
1410 tsp->ipRank = rank; /* no need to protect by mutex*/
1412 if (type == CM_SERVER_FILE)
1414 /* find volumes which might have RO copy
1415 /* on server and change the ordering of
1418 cm_ChangeRankVolume(tsp);
1422 /* set preferences for an existing vlserver */
1423 cm_ChangeRankCellVLServer(tsp);
1425 cm_PutServer(tsp); /* decrease refcount */
1427 else /* add a new server without a cell */
1429 tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
1436 long cm_IoctlGetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
1438 cm_SPrefRequest_t *spin; /* input */
1439 cm_SPrefInfo_t *spout; /* output */
1440 cm_SPref_t *srvout; /* one output component */
1442 int i, vlonly, noServers;
1444 cm_SkipIoctlPath(ioctlp); /* we don't care about the path */
1446 spin = (cm_SPrefRequest_t *)ioctlp->inDatap;
1447 spout = (cm_SPrefInfo_t *) ioctlp->outDatap;
1448 srvout = spout->servers;
1449 noServers = spin->num_servers;
1450 vlonly = spin->flags & CM_SPREF_VLONLY;
1451 spout->num_servers = 0;
1453 lock_ObtainRead(&cm_serverLock); /* get server lock */
1455 for (tsp=cm_allServersp, i=0; tsp && noServers; tsp=tsp->allNextp,i++){
1456 if (spin->offset > i) {
1457 continue; /* catch up to where we left off */
1460 if ( vlonly && (tsp->type == CM_SERVER_FILE) )
1461 continue; /* ignore fileserver for -vlserver option*/
1462 if ( !vlonly && (tsp->type == CM_SERVER_VLDB) )
1463 continue; /* ignore vlservers */
1465 srvout->host = tsp->addr.sin_addr;
1466 srvout->rank = tsp->ipRank;
1468 spout->num_servers++;
1471 lock_ReleaseRead(&cm_serverLock); /* release server lock */
1473 if ( tsp ) /* we ran out of space in the output buffer */
1474 spout->next_offset = i;
1476 spout->next_offset = 0;
1477 ioctlp->outDatap += sizeof(cm_SPrefInfo_t) +
1478 (spout->num_servers -1 ) * sizeof(cm_SPref_t) ;
1482 long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
1484 /* we ignore default asynchrony since we only have one way
1485 * of doing this today.
1490 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
1492 char leaf[LEAF_SIZE];
1506 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1507 if (code) return code;
1509 /* Translate chars for the mount point name */
1510 TranslateExtendedChars(leaf);
1513 * The fs command allows the user to specify partial cell names on NT. These must
1514 * be expanded to the full cell name for mount points so that the mount points will
1515 * work on UNIX clients.
1518 /* Extract the possibly partial cell name */
1519 StringCbCopyA(cell, sizeof(cell), ioctlp->inDatap + 1); /* Skip the mp type character */
1521 if (cp = strchr(cell, ':')) {
1522 /* Extract the volume name */
1524 StringCbCopyA(volume, sizeof(volume), cp + 1);
1526 /* Get the full name for this cell */
1527 code = cm_SearchCellFile(cell, fullCell, 0, 0);
1528 #ifdef AFS_AFSDB_ENV
1529 if (code && cm_dnsEnabled)
1530 code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
1533 return CM_ERROR_NOSUCHCELL;
1535 StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
1537 /* No cell name specified */
1538 StringCbCopyA(mpInfo, sizeof(mpInfo), ioctlp->inDatap);
1541 #ifdef AFS_FREELANCE_CLIENT
1542 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1543 /* we are adding the mount point to the root dir., so call
1544 * the freelance code to do the add. */
1545 osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
1546 code = cm_FreelanceAddMount(leaf, fullCell, volume,
1547 *ioctlp->inDatap == '%', NULL);
1551 /* create the symlink with mode 644. The lack of X bits tells
1552 * us that it is a mount point.
1554 tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
1555 tattr.unixModeBits = 0644;
1556 tattr.clientModTime = time(NULL);
1558 code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
1559 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1560 smb_NotifyChange(FILE_ACTION_ADDED,
1561 FILE_NOTIFY_CHANGE_DIR_NAME,
1562 dscp, leaf, NULL, TRUE);
1564 cm_ReleaseSCache(dscp);
1568 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1570 char leaf[LEAF_SIZE];
1579 code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
1580 if (code) return code;
1582 /* Translate chars for the link name */
1583 TranslateExtendedChars(leaf);
1585 /* Translate chars for the linked to name */
1586 TranslateExtendedChars(ioctlp->inDatap);
1588 cp = ioctlp->inDatap; /* contents of link */
1590 #ifdef AFS_FREELANCE_CLIENT
1591 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1592 /* we are adding the symlink to the root dir., so call
1593 * the freelance code to do the add. */
1594 if (cp[0] == cp[1] && cp[1] == '\\' &&
1595 !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName)))
1597 /* skip \\AFS\ or \\AFS\all\ */
1599 p = cp + 2 + strlen(cm_NetbiosName) + 1;
1600 if ( !_strnicmp("all", p, 3) )
1604 osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir");
1605 code = cm_FreelanceAddSymlink(leaf, cp, NULL);
1610 /* Create symlink with mode 0755. */
1611 tattr.mask = CM_ATTRMASK_UNIXMODEBITS;
1612 tattr.unixModeBits = 0755;
1614 code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, &req);
1615 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1616 smb_NotifyChange(FILE_ACTION_ADDED,
1617 FILE_NOTIFY_CHANGE_FILE_NAME
1618 | FILE_NOTIFY_CHANGE_DIR_NAME,
1619 dscp, leaf, NULL, TRUE);
1621 cm_ReleaseSCache(dscp);
1627 long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1634 cm_scache_t *newRootScp;
1639 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1640 if (code) return code;
1642 cp = ioctlp->inDatap;
1644 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1645 cm_ReleaseSCache(dscp);
1646 if (code) return code;
1648 /* Check that it's a real symlink */
1649 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1650 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1651 scp->fileType != CM_SCACHETYPE_INVALID) {
1652 cm_ReleaseSCache(scp);
1653 return CM_ERROR_INVAL;
1656 code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
1657 cm_ReleaseSCache(scp);
1659 cp = ioctlp->outDatap;
1660 if (newRootScp != NULL) {
1661 StringCbCopyA(cp, 999999, cm_mountRoot);
1662 StringCbCatA(cp, 999999, "/");
1665 StringCbCopyA(cp, 999999, spacep->data);
1666 cp += strlen(cp) + 1;
1667 ioctlp->outDatap = cp;
1668 cm_FreeSpace(spacep);
1669 if (newRootScp != NULL)
1670 cm_ReleaseSCache(newRootScp);
1672 } else if (code == CM_ERROR_PATH_NOT_COVERED &&
1673 scp->fileType == CM_SCACHETYPE_DFSLINK ||
1674 code == CM_ERROR_NOSUCHPATH &&
1675 scp->fileType == CM_SCACHETYPE_INVALID) {
1676 cp = ioctlp->outDatap;
1677 StringCbCopyA(cp, 999999, spacep->data);
1678 cp += strlen(cp) + 1;
1679 ioctlp->outDatap = cp;
1680 cm_FreeSpace(spacep);
1681 if (newRootScp != NULL)
1682 cm_ReleaseSCache(newRootScp);
1689 long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1690 {/*CHECK FOR VALID SYMLINK*/
1699 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1700 if (code) return code;
1702 cp = ioctlp->inDatap;
1703 osi_LogEvent("cm_IoctlListlink",NULL," name[%s]",cp);
1705 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1706 cm_ReleaseSCache(dscp);
1707 if (code) return code;
1709 /* Check that it's a real symlink */
1710 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1711 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1712 scp->fileType != CM_SCACHETYPE_INVALID)
1713 code = CM_ERROR_INVAL;
1714 cm_ReleaseSCache(scp);
1718 long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
1728 code = cm_ParseIoctlPath(ioctlp, userp, &req, &dscp);
1729 if (code) return code;
1731 cp = ioctlp->inDatap;
1733 #ifdef AFS_FREELANCE_CLIENT
1734 if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
1735 /* we are adding the mount point to the root dir., so call
1736 * the freelance code to do the add. */
1737 osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
1738 code = cm_FreelanceRemoveSymlink(cp);
1743 code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
1745 /* if something went wrong, bail out now */
1750 lock_ObtainMutex(&scp->mx);
1751 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1752 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1754 lock_ReleaseMutex(&scp->mx);
1755 cm_ReleaseSCache(scp);
1759 /* now check that this is a real symlink */
1760 if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
1761 scp->fileType != CM_SCACHETYPE_DFSLINK &&
1762 scp->fileType != CM_SCACHETYPE_INVALID) {
1763 lock_ReleaseMutex(&scp->mx);
1764 cm_ReleaseSCache(scp);
1765 code = CM_ERROR_INVAL;
1769 /* time to make the RPC, so drop the lock */
1770 lock_ReleaseMutex(&scp->mx);
1771 cm_ReleaseSCache(scp);
1773 /* easier to do it this way */
1774 code = cm_Unlink(dscp, cp, userp, &req);
1775 if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
1776 smb_NotifyChange(FILE_ACTION_REMOVED,
1777 FILE_NOTIFY_CHANGE_FILE_NAME
1778 | FILE_NOTIFY_CHANGE_DIR_NAME,
1779 dscp, cp, NULL, TRUE);
1782 cm_ReleaseSCache(dscp);
1786 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
1793 struct ClearToken ct;
1802 saveDataPtr = ioctlp->inDatap;
1804 cm_SkipIoctlPath(ioctlp);
1806 tp = ioctlp->inDatap;
1809 memcpy(&ticketLen, tp, sizeof(ticketLen));
1810 tp += sizeof(ticketLen);
1811 if (ticketLen < MINKTCTICKETLEN || ticketLen > MAXKTCTICKETLEN)
1812 return CM_ERROR_INVAL;
1814 /* remember ticket and skip over it for now */
1818 /* clear token size */
1819 memcpy(&ctSize, tp, sizeof(ctSize));
1820 tp += sizeof(ctSize);
1821 if (ctSize != sizeof(struct ClearToken))
1822 return CM_ERROR_INVAL;
1825 memcpy(&ct, tp, ctSize);
1827 if (ct.AuthHandle == -1)
1828 ct.AuthHandle = 999; /* more rxvab compat stuff */
1830 /* more stuff, if any */
1831 if (ioctlp->inCopied > tp - saveDataPtr) {
1832 /* flags: logon flag */
1833 memcpy(&flags, tp, sizeof(int));
1837 cellp = cm_GetCell(tp, CM_FLAG_CREATE);
1838 if (!cellp) return CM_ERROR_NOSUCHCELL;
1839 tp += strlen(tp) + 1;
1843 tp += strlen(tp) + 1;
1845 #ifndef AFSIFS /* no SMB username, so we cannot log based on this */
1846 if (flags & PIOCTL_LOGON) {
1847 /* SMB user name with which to associate tokens */
1849 osi_Log2(smb_logp,"cm_IoctlSetToken for user [%s] smbname [%s]",
1850 osi_LogSaveString(smb_logp,uname), osi_LogSaveString(smb_logp,smbname));
1851 fprintf(stderr, "SMB name = %s\n", smbname);
1852 tp += strlen(tp) + 1;
1854 osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
1855 osi_LogSaveString(smb_logp,uname));
1859 #ifndef DJGPP /* for win95, session key is back in pioctl */
1861 memcpy(&uuid, tp, sizeof(uuid));
1862 if (!cm_FindTokenEvent(uuid, sessionKey))
1863 return CM_ERROR_INVAL;
1866 cellp = cm_data.rootCellp;
1867 osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
1870 if (flags & PIOCTL_LOGON) {
1871 userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname);
1874 /* store the token */
1875 lock_ObtainMutex(&userp->mx);
1876 ucellp = cm_GetUCell(userp, cellp);
1877 osi_Log1(smb_logp,"cm_IoctlSetToken ucellp %lx", ucellp);
1878 ucellp->ticketLen = ticketLen;
1879 if (ucellp->ticketp)
1880 free(ucellp->ticketp); /* Discard old token if any */
1881 ucellp->ticketp = malloc(ticketLen);
1882 memcpy(ucellp->ticketp, ticket, ticketLen);
1885 * Get the session key from the RPC, rather than from the pioctl.
1888 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1890 memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
1892 /* for win95, we are getting the session key from the pioctl */
1893 memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
1895 ucellp->kvno = ct.AuthHandle;
1896 ucellp->expirationTime = ct.EndTimestamp;
1899 StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
1900 ucellp->flags |= CM_UCELLFLAG_RXKAD;
1901 lock_ReleaseMutex(&userp->mx);
1903 if (flags & PIOCTL_LOGON) {
1904 ioctlp->flags |= SMB_IOCTLFLAG_LOGON;
1907 cm_ResetACLCache(userp);
1912 long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
1918 struct ClearToken ct;
1920 cm_SkipIoctlPath(ioctlp);
1922 tp = ioctlp->inDatap;
1923 cp = ioctlp->outDatap;
1926 memcpy(&iterator, tp, sizeof(iterator));
1927 tp += sizeof(iterator);
1929 lock_ObtainMutex(&userp->mx);
1931 /* look for token */
1932 for (;;iterator++) {
1933 ucellp = cm_FindUCell(userp, iterator);
1935 lock_ReleaseMutex(&userp->mx);
1936 return CM_ERROR_NOMORETOKENS;
1938 if (ucellp->flags & CM_UCELLFLAG_RXKAD)
1943 temp = ucellp->iterator + 1;
1944 memcpy(cp, &temp, sizeof(temp));
1948 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
1949 cp += sizeof(ucellp->ticketLen);
1952 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
1953 cp += ucellp->ticketLen;
1955 /* clear token size */
1957 memcpy(cp, &temp, sizeof(temp));
1961 ct.AuthHandle = ucellp->kvno;
1964 * Don't give out a real session key here
1967 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
1969 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
1971 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
1973 ct.ViceId = 37; /* XXX */
1974 ct.BeginTimestamp = 0; /* XXX */
1975 ct.EndTimestamp = ucellp->expirationTime;
1976 memcpy(cp, &ct, sizeof(ct));
1979 /* Primary flag (unused) */
1981 memcpy(cp, &temp, sizeof(temp));
1985 StringCbCopyA(cp, 999999, ucellp->cellp->name);
1986 cp += strlen(cp) + 1;
1989 StringCbCopyA(cp, 999999, ucellp->userName);
1990 cp += strlen(cp) + 1;
1992 ioctlp->outDatap = cp;
1994 lock_ReleaseMutex(&userp->mx);
1999 long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2005 struct ClearToken ct;
2011 cm_SkipIoctlPath(ioctlp);
2013 tp = ioctlp->inDatap;
2015 cp = ioctlp->outDatap;
2017 /* cell name is right here */
2018 cellp = cm_GetCell(tp, 0);
2020 return CM_ERROR_NOSUCHCELL;
2021 tp += strlen(tp) + 1;
2025 memcpy(&uuid, tp, sizeof(uuid));
2028 lock_ObtainMutex(&userp->mx);
2030 ucellp = cm_GetUCell(userp, cellp);
2031 if (!ucellp || !(ucellp->flags & CM_UCELLFLAG_RXKAD)) {
2032 lock_ReleaseMutex(&userp->mx);
2033 return CM_ERROR_NOMORETOKENS;
2037 memcpy(cp, &ucellp->ticketLen, sizeof(ucellp->ticketLen));
2038 cp += sizeof(ucellp->ticketLen);
2041 memcpy(cp, ucellp->ticketp, ucellp->ticketLen);
2042 cp += ucellp->ticketLen;
2044 /* clear token size */
2046 memcpy(cp, &temp, sizeof(temp));
2050 ct.AuthHandle = ucellp->kvno;
2053 * Don't give out a real session key here
2056 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2058 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
2060 memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
2062 ct.ViceId = 37; /* XXX */
2063 ct.BeginTimestamp = 0; /* XXX */
2064 ct.EndTimestamp = ucellp->expirationTime;
2065 memcpy(cp, &ct, sizeof(ct));
2068 /* Primary flag (unused) */
2070 memcpy(cp, &temp, sizeof(temp));
2074 StringCbCopyA(cp, 999999, ucellp->cellp->name);
2075 cp += strlen(cp) + 1;
2078 StringCbCopyA(cp, 999999, ucellp->userName);
2079 cp += strlen(cp) + 1;
2081 ioctlp->outDatap = cp;
2083 lock_ReleaseMutex(&userp->mx);
2086 cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
2092 long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2098 cm_SkipIoctlPath(ioctlp);
2100 cp = ioctlp->outDatap;
2102 /* cell name is right here */
2103 cellp = cm_GetCell(ioctlp->inDatap, 0);
2104 if (!cellp) return CM_ERROR_NOSUCHCELL;
2106 lock_ObtainMutex(&userp->mx);
2108 ucellp = cm_GetUCell(userp, cellp);
2110 lock_ReleaseMutex(&userp->mx);
2111 return CM_ERROR_NOMORETOKENS;
2114 osi_Log1(smb_logp,"cm_IoctlDelToken ucellp %lx", ucellp);
2116 if (ucellp->ticketp) {
2117 free(ucellp->ticketp);
2118 ucellp->ticketp = NULL;
2120 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2123 lock_ReleaseMutex(&userp->mx);
2125 cm_ResetACLCache(userp);
2130 long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
2134 lock_ObtainMutex(&userp->mx);
2136 for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
2137 osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
2138 ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
2142 lock_ReleaseMutex(&userp->mx);
2144 cm_ResetACLCache(userp);
2149 long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
2151 char afspath[MAX_PATH];
2153 int nextAutoSubmount;
2155 DWORD dwType, dwSize;
2160 cm_SkipIoctlPath(ioctlp);
2162 /* Serialize this one, to prevent simultaneous mods
2165 lock_ObtainMutex(&cm_Afsdsbmt_Lock);
2167 /* Parse the input parameters--first the required afs path,
2168 * then the requested submount name (which may be "").
2170 cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
2171 submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
2173 /* If the caller supplied a suggested submount name, see if
2174 * that submount name is in use... if so, the submount's path
2175 * has to match our path.
2178 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
2179 AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
2182 REG_OPTION_NON_VOLATILE,
2183 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
2188 if (submountreqp && *submountreqp) {
2189 char submountPathNormalized[MAX_PATH];
2190 char submountPath[MAX_PATH];
2192 dwSize = sizeof(submountPath);
2193 status = RegQueryValueEx( hkSubmounts, submountreqp, 0,
2194 &dwType, submountPath, &dwSize);
2196 if (status != ERROR_SUCCESS) {
2198 /* The suggested submount name isn't in use now--
2199 * so we can safely map the requested submount name
2200 * to the supplied path. Remember not to write the
2201 * leading "/afs" when writing out the submount.
2203 RegSetValueEx( hkSubmounts, submountreqp, 0,
2205 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2206 &afspath[strlen(cm_mountRoot)]:"/",
2207 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2208 strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2210 RegCloseKey( hkSubmounts );
2211 StringCbCopyA(ioctlp->outDatap, 999999, submountreqp);
2212 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2213 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2217 /* The suggested submount name is already in use--if the
2218 * supplied path matches the submount's path, we can still
2219 * use the suggested submount name.
2221 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2222 if (!strcmp (submountPathNormalized, afspath)) {
2223 StringCbCopyA(ioctlp->outDatap, 999999, submountreqp);
2224 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2225 RegCloseKey( hkSubmounts );
2226 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2231 RegQueryInfoKey( hkSubmounts,
2233 NULL, /* lpcClass */
2234 NULL, /* lpReserved */
2235 NULL, /* lpcSubKeys */
2236 NULL, /* lpcMaxSubKeyLen */
2237 NULL, /* lpcMaxClassLen */
2238 &dwSubmounts, /* lpcValues */
2239 NULL, /* lpcMaxValueNameLen */
2240 NULL, /* lpcMaxValueLen */
2241 NULL, /* lpcbSecurityDescriptor */
2242 NULL /* lpftLastWriteTime */
2246 /* Having obtained a list of all available submounts, start
2247 * searching that list for a path which matches the requested
2248 * AFS path. We'll also keep track of the highest "auto15"/"auto47"
2249 * submount, in case we need to add a new one later.
2252 nextAutoSubmount = 1;
2254 for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
2255 char submountPathNormalized[MAX_PATH];
2256 char submountPath[MAX_PATH] = "";
2257 DWORD submountPathLen = sizeof(submountPath);
2258 char submountName[MAX_PATH];
2259 DWORD submountNameLen = sizeof(submountName);
2262 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
2263 &dwType, submountPath, &submountPathLen);
2264 if (dwType == REG_EXPAND_SZ) {
2266 StringCbCopyA(buf, MAX_PATH, submountPath);
2267 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
2268 if (submountPathLen > MAX_PATH)
2272 /* If this is an Auto### submount, remember its ### value */
2273 if ((!strnicmp (submountName, "auto", 4)) &&
2274 (isdigit (submountName[strlen("auto")]))) {
2275 int thisAutoSubmount;
2276 thisAutoSubmount = atoi (&submountName[strlen("auto")]);
2277 nextAutoSubmount = max (nextAutoSubmount,
2278 thisAutoSubmount+1);
2281 if ((submountPathLen == 0) ||
2282 (submountPathLen == sizeof(submountPath) - 1)) {
2286 /* See if the path for this submount matches the path
2287 * that our caller specified. If so, we can return
2290 cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
2291 if (!strcmp (submountPathNormalized, afspath)) {
2292 StringCbCopyA(ioctlp->outDatap, 999999, submountName);
2293 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2294 RegCloseKey(hkSubmounts);
2295 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2301 /* We've been through the entire list of existing submounts, and
2302 * didn't find any which matched the specified path. So, we'll
2303 * just have to add one. Remember not to write the leading "/afs"
2304 * when writing out the submount.
2307 StringCbPrintfA(ioctlp->outDatap, 999999, "auto%ld", nextAutoSubmount);
2309 RegSetValueEx( hkSubmounts,
2313 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2314 &afspath[strlen(cm_mountRoot)]:"/",
2315 (strlen(&afspath[strlen(cm_mountRoot)])) ?
2316 strlen(&afspath[strlen(cm_mountRoot)])+1:2);
2318 ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
2319 RegCloseKey(hkSubmounts);
2320 lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
2324 long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2326 memcpy(ioctlp->outDatap, &cryptall, sizeof(cryptall));
2327 ioctlp->outDatap += sizeof(cryptall);
2332 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
2334 cm_SkipIoctlPath(ioctlp);
2336 memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
2342 extern int afsd_shutdown(int);
2343 extern int afs_shutdown;
2345 long cm_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp) {
2346 afs_shutdown = 1; /* flag to shut down */
2351 long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
2353 smb_user_t *uidp = ioctlp->uidp;
2355 if (uidp && uidp->unp) {
2356 memcpy(ioctlp->outDatap, uidp->unp->name, strlen(uidp->unp->name));
2357 ioctlp->outDatap += strlen(uidp->unp->name);
2364 * functions to dump contents of various structures.
2365 * In debug build (linked with crt debug library) will dump allocated but not freed memory
2367 extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
2368 extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
2369 extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
2371 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
2375 char logfileName[MAX_PATH+1];
2380 static _CrtMemState memstate;
2383 cm_SkipIoctlPath(ioctlp);
2384 memcpy(&inValue, ioctlp->inDatap, sizeof(long));
2386 dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
2387 if ( dwSize == 0 || dwSize > sizeof(logfileName) )
2389 GetWindowsDirectory(logfileName, sizeof(logfileName));
2391 strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
2393 hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2399 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2400 ioctlp->outDatap += sizeof(long);
2405 SetFilePointer(hLogFile, 0, NULL, FILE_END);
2407 cookie = inValue ? "b" : "e";
2413 _CrtMemCheckpoint(&memstate);
2417 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2418 _CrtSetReportFile(_CRT_WARN, hLogFile);
2419 _CrtMemDumpAllObjectsSince(&memstate);
2423 /* dump all interesting data */
2424 cm_DumpSCache(hLogFile, cookie, 1);
2425 cm_DumpBufHashTable(hLogFile, cookie, 1);
2426 smb_DumpVCP(hLogFile, cookie, 1);
2428 CloseHandle(hLogFile);
2430 memcpy(ioctlp->outDatap, &inValue, sizeof(long));
2431 ioctlp->outDatap += sizeof(long);