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 <afsconfig.h>
11 #include <afs/param.h>
34 #include <cm_scache.h>
40 #include <pioctl_nt.h>
42 /* Are we using the canonical Netbios name (AFS)? */
43 BOOL smb_TruncateNetbios = FALSE; /* what the registry says */
44 BOOL smb_TruncateNetbiosReal = FALSE; /* what we actually grant */
46 static char AFSConfigKeyName[] =
47 "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
49 #define FS_IOCTLREQUEST_MAXSIZE 8192
50 /* big structure for representing and storing an IOCTL request */
51 typedef struct fs_ioctlRequest {
52 char *mp; /* marshalling/unmarshalling ptr */
53 long nbytes; /* bytes received (when unmarshalling) */
54 char data[FS_IOCTLREQUEST_MAXSIZE]; /* data we're marshalling */
58 CMtoUNIXerror(int cm_code)
61 case CM_ERROR_TIMEDOUT:
63 case CM_ERROR_NOACCESS:
65 case CM_ERROR_NOSUCHFILE:
73 case CM_ERROR_CROSSDEVLINK:
79 case CM_ERROR_READONLY:
81 case CM_ERROR_WOULDBLOCK:
83 case CM_ERROR_NOSUCHCELL:
84 return ESRCH; /* hack */
85 case CM_ERROR_NOSUCHVOLUME:
86 return EPIPE; /* hack */
87 case CM_ERROR_NOMORETOKENS:
88 return EDOM; /* hack */
89 case CM_ERROR_TOOMANYBUFS:
90 return EFBIG; /* hack */
97 InitFSRequest(fs_ioctlRequest_t * rp)
104 GetIoctlHandle(char *fileNamep, HANDLE * handlep)
110 char explicitNetbiosName[32];
119 drivep = strchr(fileNamep, ':');
120 if (drivep && (drivep - fileNamep) >= 1) {
121 tbuffer[0] = *(drivep - 1);
123 strcpy(tbuffer + 2, SMB_IOCTL_FILENAME);
125 strcpy(tbuffer, SMB_IOCTL_FILENAME);
127 /* No file name specified, use UNC name */
128 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0,
129 KEY_QUERY_VALUE, &parmKey);
130 if (code != ERROR_SUCCESS)
133 dummyLen = sizeof(buf);
134 code = RegQueryValueEx(parmKey, "TruncateNetbios", NULL, NULL,
135 (BYTE *) buf, &dummyLen);
136 if (code == ERROR_SUCCESS)
138 if (!stricmp( (const char *) buf, "on"))
140 smb_TruncateNetbios = TRUE;
141 smb_TruncateNetbiosReal = TRUE;
145 dummyLen = sizeof(isGateway);
146 code = RegQueryValueEx(parmKey, "IsGateway", NULL, NULL,
147 (BYTE *) &isGateway, &dummyLen);
149 /* Is there an explicit name we should use? */
150 dummyLen = sizeof(explicitNetbiosName);
151 code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL,
152 (BYTE *) &explicitNetbiosName, &dummyLen);
153 if (!code == ERROR_SUCCESS)
155 explicitNetbiosName[0] = 0;
158 /* Look for gateway host in Registry */
159 dummyLen = sizeof(hostName);
160 code = RegQueryValueEx(parmKey, "Gateway", NULL, NULL, hostName,
162 RegCloseKey(parmKey);
163 if (code == ERROR_SUCCESS)
167 /* No gateway name in registry; use ourself */
168 #ifndef AFS_WIN95_ENV
169 gethostname(hostName, sizeof(hostName));
173 /* DJGPP version of gethostname gets the NetBIOS
174 * name of the machine, so that is what we are using for
175 * the AFS server name instead of the DNS name. */
176 hostsize = sizeof(hostName);
177 GetComputerName(hostName, &hostsize);
179 #endif /* AFS_WIN95_ENV */
182 ctemp = strchr(hostName, '.'); /* turn ntafs.* into ntafs */
187 if (explicitNetbiosName[0])
189 _strupr(explicitNetbiosName);
190 sprintf(tbuffer, "\\\\%s\\all%s",
191 explicitNetbiosName, SMB_IOCTL_FILENAME);
193 else if (smb_TruncateNetbiosReal) {
194 sprintf(tbuffer, "\\\\AFS\\all%s", SMB_IOCTL_FILENAME);
199 sprintf(tbuffer, "\\\\%s-AFS\\all%s",
200 hostName, SMB_IOCTL_FILENAME);
205 /* now open the file */
206 fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
207 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
208 FILE_FLAG_WRITE_THROUGH, NULL);
210 if (fh == INVALID_HANDLE_VALUE)
213 /* return fh and success code */
219 Transceive(HANDLE handle, fs_ioctlRequest_t * reqp)
224 rcount = reqp->mp - reqp->data;
226 return EINVAL; /* not supposed to happen */
228 if (!WriteFile(handle, reqp->data, rcount, &ioCount, NULL)) {
229 /* failed to write */
230 return GetLastError();
233 if (!ReadFile(handle, reqp->data, sizeof(reqp->data), &ioCount, NULL)) {
235 return GetLastError();
238 reqp->nbytes = ioCount; /* set # of bytes available */
239 reqp->mp = reqp->data; /* restart marshalling */
246 MarshallLong(fs_ioctlRequest_t * reqp, long val)
248 memcpy(reqp->mp, &val, 4);
254 UnmarshallLong(fs_ioctlRequest_t * reqp, long *valp)
256 /* not enough data left */
257 if (reqp->nbytes < 4) {
261 memcpy(valp, reqp->mp, 4);
267 /* includes marshalling NULL pointer as a null (0 length) string */
269 MarshallString(fs_ioctlRequest_t * reqp, char *stringp)
274 count = strlen(stringp) + 1; /* space required including null */
278 /* watch for buffer overflow */
279 if ((reqp->mp - reqp->data) + count > sizeof(reqp->data))
283 memcpy(reqp->mp, stringp, count);
290 /* take a path with a drive letter, possibly relative, and return a full path
291 * without the drive letter. This is the full path relative to the working
292 * dir for that drive letter. The input and output paths can be the same.
295 fs_GetFullPath(char *pathp, char *outPathp, long outSize)
305 if (pathp[0] != 0 && pathp[1] == ':') {
306 /* there's a drive letter there */
314 if (*firstp == '\\' || *firstp == '/') {
315 /* already an absolute pathname, just copy it back */
316 strcpy(outPathp, firstp);
320 GetCurrentDirectory(sizeof(origPath), origPath);
323 if (pathHasDrive && (*pathp & ~0x20) != (origPath[0] & ~0x20)) {
324 /* a drive has been specified and it isn't our current drive.
325 * to get path, switch to it first. Must case-fold drive letters
326 * for user convenience.
332 if (!SetCurrentDirectory(newPath)) {
333 code = GetLastError();
338 /* now get the absolute path to the current wdir in this drive */
339 GetCurrentDirectory(sizeof(tpath), tpath);
340 strcpy(outPathp, tpath + 2); /* skip drive letter */
341 /* if there is a non-null name after the drive, append it */
343 strcat(outPathp, "\\");
344 strcat(outPathp, firstp);
347 /* finally, if necessary, switch back to our home drive letter */
349 SetCurrentDirectory(origPath);
356 pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow)
358 fs_ioctlRequest_t preq;
364 code = GetIoctlHandle(pathp, &reqHandle);
373 /* init the request structure */
374 InitFSRequest(&preq);
376 /* marshall the opcode, the path name and the input parameters */
377 MarshallLong(&preq, opcode);
378 /* when marshalling the path, remove the drive letter, since we already
379 * used the drive letter to find the AFS daemon; we don't need it any more.
380 * Eventually we'll expand relative path names here, too, since again, only
381 * we understand those.
384 code = fs_GetFullPath(pathp, fullPath, sizeof(fullPath));
386 CloseHandle(reqHandle);
391 strcpy(fullPath, "");
394 MarshallString(&preq, fullPath);
395 if (blobp->in_size) {
396 memcpy(preq.mp, blobp->in, blobp->in_size);
397 preq.mp += blobp->in_size;
400 /* now make the call */
401 code = Transceive(reqHandle, &preq);
403 CloseHandle(reqHandle);
407 /* now unmarshall the return value */
408 UnmarshallLong(&preq, &temp);
410 CloseHandle(reqHandle);
411 errno = CMtoUNIXerror(temp);
415 /* otherwise, unmarshall the output parameters */
416 if (blobp->out_size) {
417 temp = blobp->out_size;
418 if (preq.nbytes < temp)
420 memcpy(blobp->out, preq.mp, temp);
421 blobp->out_size = temp;
424 /* and return success */
425 CloseHandle(reqHandle);