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>
25 #define SECURITY_WIN32
33 #include <cm_server.h>
37 #include <cm_scache.h>
44 #include <pioctl_nt.h>
45 #include <WINNT/afsreg.h>
46 #include <lanahelper.h>
48 #include <loadfuncs-krb5.h>
51 static char AFSConfigKeyName[] = AFSREG_CLT_SVC_PARAM_SUBKEY;
53 static const char utf8_prefix[] = UTF8_PREFIX;
54 static const int utf8_prefix_size = sizeof(utf8_prefix) - sizeof(char);
56 #define FS_IOCTLREQUEST_MAXSIZE 8192
57 /* big structure for representing and storing an IOCTL request */
58 typedef struct fs_ioctlRequest {
59 char *mp; /* marshalling/unmarshalling ptr */
60 long nbytes; /* bytes received (when unmarshalling) */
61 char data[FS_IOCTLREQUEST_MAXSIZE]; /* data we're marshalling */
65 CMtoUNIXerror(int cm_code)
68 case CM_ERROR_TIMEDOUT:
70 case CM_ERROR_NOACCESS:
72 case CM_ERROR_NOSUCHFILE:
73 case CM_ERROR_NOSUCHPATH:
74 case CM_ERROR_BPLUS_NOMATCH:
81 case CM_ERROR_INEXACT_MATCH:
83 case CM_ERROR_CROSSDEVLINK:
89 case CM_ERROR_READONLY:
91 case CM_ERROR_WOULDBLOCK:
93 case CM_ERROR_NOSUCHCELL:
94 return ESRCH; /* hack */
95 case CM_ERROR_NOSUCHVOLUME:
96 return EPIPE; /* hack */
97 case CM_ERROR_NOMORETOKENS:
98 return EDOM; /* hack */
99 case CM_ERROR_TOOMANYBUFS:
100 return EFBIG; /* hack */
101 case CM_ERROR_ALLBUSY:
103 case CM_ERROR_ALLDOWN:
104 return ENOSYS; /* hack */
105 case CM_ERROR_ALLOFFLINE:
106 return ENXIO; /* hack */
108 if (cm_code > 0 && cm_code < EILSEQ)
116 InitFSRequest(fs_ioctlRequest_t * rp)
126 static BOOL debug = 0;
131 if (RegOpenKey (HKEY_LOCAL_MACHINE,
132 TEXT("Software\\OpenAFS\\Client"), &hk) == 0)
134 DWORD dwSize = sizeof(BOOL);
135 DWORD dwType = REG_DWORD;
136 RegQueryValueEx (hk, TEXT("IoctlDebug"), NULL, &dwType, (PBYTE)&debug, &dwSize);
147 DisableServiceManagerCheck(void)
150 static BOOL smcheck = 0;
155 if (RegOpenKey (HKEY_LOCAL_MACHINE,
156 TEXT("Software\\OpenAFS\\Client"), &hk) == 0)
158 DWORD dwSize = sizeof(BOOL);
159 DWORD dwType = REG_DWORD;
160 RegQueryValueEx (hk, TEXT("DisableIoctlSMCheck"), NULL, &dwType, (PBYTE)&smcheck, &dwSize);
172 LPSTR lpszMachineName,
173 LPSTR lpszServiceName,
174 DWORD *lpdwCurrentState)
177 SC_HANDLE schSCManager = NULL;
178 SC_HANDLE schService = NULL;
179 DWORD fdwDesiredAccess = 0;
180 SERVICE_STATUS ssServiceStatus = {0};
183 *lpdwCurrentState = 0;
185 fdwDesiredAccess = GENERIC_READ;
187 schSCManager = OpenSCManager(lpszMachineName,
191 if(schSCManager == NULL)
197 schService = OpenService(schSCManager,
201 if(schService == NULL)
207 fRet = QueryServiceStatus(schService,
216 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
220 CloseServiceHandle(schService);
221 CloseServiceHandle(schSCManager);
227 DECL_FUNC_PTR(krb5_cc_default_name);
228 DECL_FUNC_PTR(krb5_cc_set_default_name);
229 DECL_FUNC_PTR(krb5_get_default_config_files);
230 DECL_FUNC_PTR(krb5_free_config_files);
231 DECL_FUNC_PTR(krb5_free_context);
232 DECL_FUNC_PTR(krb5_get_default_realm);
233 DECL_FUNC_PTR(krb5_free_default_realm);
234 DECL_FUNC_PTR(krb5_init_context);
235 DECL_FUNC_PTR(krb5_cc_default);
236 DECL_FUNC_PTR(krb5_parse_name);
237 DECL_FUNC_PTR(krb5_free_principal);
238 DECL_FUNC_PTR(krb5_cc_close);
239 DECL_FUNC_PTR(krb5_cc_get_principal);
240 DECL_FUNC_PTR(krb5_build_principal);
241 DECL_FUNC_PTR(krb5_c_random_make_octets);
242 DECL_FUNC_PTR(krb5_get_init_creds_password);
243 DECL_FUNC_PTR(krb5_free_cred_contents);
244 DECL_FUNC_PTR(krb5_cc_resolve);
245 DECL_FUNC_PTR(krb5_unparse_name);
246 DECL_FUNC_PTR(krb5_free_unparsed_name);
248 FUNC_INFO krb5_fi[] = {
249 MAKE_FUNC_INFO(krb5_cc_default_name),
250 MAKE_FUNC_INFO(krb5_cc_set_default_name),
251 MAKE_FUNC_INFO(krb5_get_default_config_files),
252 MAKE_FUNC_INFO(krb5_free_config_files),
253 MAKE_FUNC_INFO(krb5_free_context),
254 MAKE_FUNC_INFO(krb5_get_default_realm),
255 MAKE_FUNC_INFO(krb5_free_default_realm),
256 MAKE_FUNC_INFO(krb5_init_context),
257 MAKE_FUNC_INFO(krb5_cc_default),
258 MAKE_FUNC_INFO(krb5_parse_name),
259 MAKE_FUNC_INFO(krb5_free_principal),
260 MAKE_FUNC_INFO(krb5_cc_close),
261 MAKE_FUNC_INFO(krb5_cc_get_principal),
262 MAKE_FUNC_INFO(krb5_build_principal),
263 MAKE_FUNC_INFO(krb5_c_random_make_octets),
264 MAKE_FUNC_INFO(krb5_get_init_creds_password),
265 MAKE_FUNC_INFO(krb5_free_cred_contents),
266 MAKE_FUNC_INFO(krb5_cc_resolve),
267 MAKE_FUNC_INFO(krb5_unparse_name),
268 MAKE_FUNC_INFO(krb5_free_unparsed_name),
274 const char* dll_name,
276 HINSTANCE* ph, // [out, optional] - DLL handle
277 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
278 int cleanup, // cleanup function pointers and unload on error
279 int go_on, // continue loading even if some functions cannot be loaded
280 int silent // do not pop-up a system dialog if DLL cannot be loaded
289 if (pindex) *pindex = -1;
291 for (n = 0; fi[n].func_ptr_var; n++)
292 *(fi[n].func_ptr_var) = 0;
295 em = SetErrorMode(SEM_FAILCRITICALERRORS);
296 h = LoadLibrary(dll_name);
304 for (i = 0; (go_on || !error) && (i < n); i++)
306 void* p = (void*)GetProcAddress(h, fi[i].func_name);
312 *(fi[i].func_ptr_var) = p;
315 if (pindex) *pindex = last_i;
316 if (error && cleanup && !go_on) {
317 for (i = 0; i < n; i++) {
318 *(fi[i].func_ptr_var) = 0;
327 #if defined(_IA64_) || defined(_AMD64_)
328 #define KERB5DLL "krb5_64.dll"
330 #define KERB5DLL "krb5_32.dll"
335 static HINSTANCE hKrb5DLL = 0;
340 hKrb5DLL = LoadLibrary(KERB5DLL);
342 if (!LoadFuncs(KERB5DLL, krb5_fi, 0, 0, 1, 0, 0))
344 FreeLibrary(hKrb5DLL);
354 GetLSAPrincipalName(char * szUser, DWORD *dwSize)
356 krb5_context ctx = 0;
357 krb5_error_code code;
358 krb5_ccache mslsa_ccache=0;
359 krb5_principal princ = 0;
363 if (!IsKrb5Available())
366 if (code = pkrb5_init_context(&ctx))
369 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
372 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
375 if (code = pkrb5_unparse_name(ctx, princ, &pname))
378 if ( strlen(pname) < *dwSize ) {
379 strncpy(szUser, pname, *dwSize);
380 szUser[*dwSize-1] = '\0';
383 *dwSize = (DWORD)strlen(pname);
387 pkrb5_free_unparsed_name(ctx, pname);
390 pkrb5_free_principal(ctx, princ);
393 pkrb5_cc_close(ctx, mslsa_ccache);
396 pkrb5_free_context(ctx);
401 DriveIsMappedToAFS(char *drivestr)
404 char NetbiosName[32] = "AFS";
405 DWORD dwResult, dwResultEnum;
407 DWORD cbBuffer = 16384; // 16K is a good size
408 DWORD cEntries = -1; // enumerate all possible entries
409 LPNETRESOURCE lpnrLocal; // pointer to enumerated structures
413 if (RegOpenKey (HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, &hk) == 0)
415 DWORD dwSize = sizeof(NetbiosName);
416 DWORD dwType = REG_SZ;
417 RegQueryValueExA (hk, "NetbiosName", NULL, &dwType, (PBYTE)NetbiosName, &dwSize);
422 // Call the WNetOpenEnum function to begin the enumeration.
424 dwResult = WNetOpenEnum(RESOURCE_CONNECTED,
427 NULL, // NULL first time the function is called
428 &hEnum); // handle to the resource
430 if (dwResult != NO_ERROR)
434 // Call the GlobalAlloc function to allocate resources.
436 lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
437 if (lpnrLocal == NULL)
442 // Initialize the buffer.
444 ZeroMemory(lpnrLocal, cbBuffer);
446 // Call the WNetEnumResource function to continue
450 dwResultEnum = WNetEnumResource(hEnum, // resource handle
451 &cEntries, // defined locally as -1
452 lpnrLocal, // LPNETRESOURCE
453 &cbBuffer); // buffer size
455 // If the call succeeds, loop through the structures.
457 if (dwResultEnum == NO_ERROR) {
458 for (i = 0; i < cEntries; i++) {
459 if (toupper(lpnrLocal[i].lpLocalName[0]) == toupper(drivestr[0])) {
461 // Skip the two backslashes at the start of the UNC device name
463 if ( _strnicmp( &(lpnrLocal[i].lpRemoteName[2]), NetbiosName, strlen(NetbiosName)) == 0 )
473 else if (dwResultEnum != ERROR_NO_MORE_ITEMS)
476 while (dwResultEnum != ERROR_NO_MORE_ITEMS);
479 // Call the GlobalFree function to free the memory.
481 GlobalFree((HGLOBAL) lpnrLocal);
483 // Call WNetCloseEnum to end the enumeration.
485 dwResult = WNetCloseEnum(hEnum);
491 GetIoctlHandle(char *fileNamep, HANDLE * handlep)
494 char netbiosName[MAX_NB_NAME_LENGTH];
495 DWORD CurrentState = 0;
496 char HostName[64] = "";
497 char tbuffer[MAX_PATH]="";
500 char szUser[128] = "";
501 char szClient[MAX_PATH] = "";
502 char szPath[MAX_PATH] = "";
505 DWORD ioctlDebug = IoctlDebug();
507 DWORD dwSize = sizeof(szUser);
510 memset(HostName, '\0', sizeof(HostName));
511 gethostname(HostName, sizeof(HostName));
512 if (!DisableServiceManagerCheck() &&
513 GetServiceStatus(HostName, TEXT("TransarcAFSDaemon"), &CurrentState) == NOERROR &&
514 CurrentState != SERVICE_RUNNING)
518 drivep = strchr(fileNamep, ':');
519 if (drivep && (drivep - fileNamep) >= 1) {
521 tbuffer[0] = *(drivep - 1);
526 driveType = GetDriveType(tbuffer);
530 if (DriveIsMappedToAFS(tbuffer))
531 strcpy(&tbuffer[2], SMB_IOCTL_FILENAME);
538 } else if (fileNamep[0] == fileNamep[1] &&
539 (fileNamep[0] == '\\' || fileNamep[0] == '/'))
541 int count = 0, i = 0;
543 while (count < 4 && fileNamep[i]) {
544 tbuffer[i] = fileNamep[i];
545 if ( tbuffer[i] == '\\' ||
550 if (fileNamep[i] == 0)
553 strcat(tbuffer, SMB_IOCTL_FILENAME);
555 char curdir[MAX_PATH]="";
557 GetCurrentDirectory(sizeof(curdir), curdir);
558 if ( curdir[1] == ':' ) {
559 tbuffer[0] = curdir[0];
561 strcpy(tbuffer + 2, SMB_IOCTL_FILENAME);
562 } else if (curdir[0] == curdir[1] &&
563 (curdir[0] == '\\' || curdir[0] == '/'))
565 int count = 0, i = 0;
567 while (count < 4 && curdir[i]) {
568 tbuffer[i] = curdir[i];
569 if ( tbuffer[i] == '\\' ||
577 strcat(tbuffer, SMB_IOCTL_FILENAME_NOSLASH);
582 /* No file name starting with drive colon specified, use UNC name */
583 lana_GetNetbiosName(netbiosName,LANA_NETBIOS_NAME_FULL);
584 sprintf(tbuffer,"\\\\%s\\all%s",netbiosName,SMB_IOCTL_FILENAME);
588 /* now open the file */
589 fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
590 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
591 FILE_FLAG_WRITE_THROUGH, NULL);
595 if (fh == INVALID_HANDLE_VALUE) {
598 gle = GetLastError();
599 if (gle && ioctlDebug ) {
603 if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
606 MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
612 fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
618 lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
620 if (RegOpenKey (HKEY_CURRENT_USER,
621 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hk) == 0)
623 DWORD dwType = REG_SZ;
624 RegQueryValueEx (hk, TEXT("Logon User Name"), NULL, &dwType, (PBYTE)szUser, &dwSize);
631 fprintf(stderr, "pioctl Explorer logon user: [%s]\r\n",szUser);
634 sprintf(szPath, "\\\\%s", szClient);
635 memset (&nr, 0x00, sizeof(NETRESOURCE));
636 nr.dwType=RESOURCETYPE_DISK;
638 nr.lpRemoteName=szPath;
639 res = WNetAddConnection2(&nr,NULL,szUser,0);
643 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
650 sprintf(szPath, "\\\\%s\\all", szClient);
651 res = WNetAddConnection2(&nr,NULL,szUser,0);
655 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
663 goto try_lsa_principal;
665 fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
666 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
667 FILE_FLAG_WRITE_THROUGH, NULL);
669 if (fh == INVALID_HANDLE_VALUE) {
670 gle = GetLastError();
671 if (gle && ioctlDebug ) {
675 if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
678 MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
684 fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
694 if (fh == INVALID_HANDLE_VALUE) {
697 dwSize = sizeof(szUser);
698 if (GetLSAPrincipalName(szUser, &dwSize)) {
701 fprintf(stderr, "pioctl LSA Principal logon user: [%s]\r\n",szUser);
704 sprintf(szPath, "\\\\%s", szClient);
705 memset (&nr, 0x00, sizeof(NETRESOURCE));
706 nr.dwType=RESOURCETYPE_DISK;
708 nr.lpRemoteName=szPath;
709 res = WNetAddConnection2(&nr,NULL,szUser,0);
713 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
720 sprintf(szPath, "\\\\%s\\all", szClient);
721 res = WNetAddConnection2(&nr,NULL,szUser,0);
725 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
735 fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
736 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
737 FILE_FLAG_WRITE_THROUGH, NULL);
739 if (fh == INVALID_HANDLE_VALUE) {
740 gle = GetLastError();
741 if (gle && ioctlDebug ) {
745 if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
748 MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
754 fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
765 if ( fh == INVALID_HANDLE_VALUE ) {
766 dwSize = sizeof(szUser);
767 if (GetUserNameEx(NameSamCompatible, szUser, &dwSize)) {
770 fprintf(stderr, "pioctl SamCompatible logon user: [%s]\r\n",szUser);
773 sprintf(szPath, "\\\\%s", szClient);
774 memset (&nr, 0x00, sizeof(NETRESOURCE));
775 nr.dwType=RESOURCETYPE_DISK;
777 nr.lpRemoteName=szPath;
778 res = WNetAddConnection2(&nr,NULL,szUser,0);
782 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
788 sprintf(szPath, "\\\\%s\\all", szClient);
789 res = WNetAddConnection2(&nr,NULL,szUser,0);
793 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
800 fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
801 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
802 FILE_FLAG_WRITE_THROUGH, NULL);
804 if (fh == INVALID_HANDLE_VALUE) {
805 gle = GetLastError();
806 if (gle && ioctlDebug ) {
810 if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
813 MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
819 fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
827 fprintf(stderr, "GetUserNameEx(NameSamCompatible) failed: 0x%X\r\n", GetLastError());
832 /* return fh and success code */
838 Transceive(HANDLE handle, fs_ioctlRequest_t * reqp)
843 DWORD ioctlDebug = IoctlDebug();
846 rcount = (long)(reqp->mp - reqp->data);
850 fprintf(stderr, "pioctl Transceive rcount <= 0: %d\r\n",rcount);
853 return EINVAL; /* not supposed to happen */
856 if (!WriteFile(handle, reqp->data, rcount, &ioCount, NULL)) {
857 /* failed to write */
858 gle = GetLastError();
862 fprintf(stderr, "pioctl Transceive WriteFile failed: 0x%X\r\n",gle);
868 if (!ReadFile(handle, reqp->data, sizeof(reqp->data), &ioCount, NULL)) {
870 gle = GetLastError();
874 fprintf(stderr, "pioctl Transceive ReadFile failed: 0x%X\r\n",gle);
880 reqp->nbytes = ioCount; /* set # of bytes available */
881 reqp->mp = reqp->data; /* restart marshalling */
888 MarshallLong(fs_ioctlRequest_t * reqp, long val)
890 memcpy(reqp->mp, &val, 4);
896 UnmarshallLong(fs_ioctlRequest_t * reqp, long *valp)
900 /* not enough data left */
901 if (reqp->nbytes < 4) {
902 if ( IoctlDebug() ) {
904 fprintf(stderr, "pioctl UnmarshallLong reqp->nbytes < 4: %d\r\n",
911 memcpy(valp, reqp->mp, 4);
917 /* includes marshalling NULL pointer as a null (0 length) string */
919 MarshallString(fs_ioctlRequest_t * reqp, char *stringp, int is_utf8)
925 count = (int)strlen(stringp) + 1;/* space required including null */
930 count += utf8_prefix_size;
933 /* watch for buffer overflow */
934 if ((reqp->mp - reqp->data) + count > sizeof(reqp->data)) {
935 if ( IoctlDebug() ) {
937 fprintf(stderr, "pioctl MarshallString buffer overflow\r\n");
944 memcpy(reqp->mp, utf8_prefix, utf8_prefix_size);
945 reqp->mp += utf8_prefix_size;
946 count -= utf8_prefix_size;
950 memcpy(reqp->mp, stringp, count);
957 /* take a path with a drive letter, possibly relative, and return a full path
958 * without the drive letter. This is the full path relative to the working
959 * dir for that drive letter. The input and output paths can be the same.
962 fs_GetFullPath(char *pathp, char *outPathp, long outSize)
974 if (pathp[0] != 0 && pathp[1] == ':') {
975 /* there's a drive letter there */
983 if ( firstp[0] == '\\' && firstp[1] == '\\' ||
984 firstp[0] == '/' && firstp[1] == '/') {
985 /* UNC path - strip off the server and sharename */
987 for ( i=2,count=2; count < 4 && firstp[i]; i++ ) {
988 if ( firstp[i] == '\\' || firstp[i] == '/' ) {
992 if ( firstp[i] == 0 ) {
993 strcpy(outPathp,"\\");
995 strcpy(outPathp,&firstp[--i]);
997 for (p=outPathp ;*p; p++) {
1002 } else if (firstp[0] == '\\' || firstp[0] == '/') {
1003 /* already an absolute pathname, just copy it back */
1004 strcpy(outPathp, firstp);
1005 for (p=outPathp ;*p; p++) {
1012 GetCurrentDirectory(sizeof(origPath), origPath);
1015 if (pathHasDrive && (*pathp & ~0x20) != (origPath[0] & ~0x20)) {
1016 /* a drive has been specified and it isn't our current drive.
1017 * to get path, switch to it first. Must case-fold drive letters
1018 * for user convenience.
1021 newPath[0] = *pathp;
1024 if (!SetCurrentDirectory(newPath)) {
1025 code = GetLastError();
1027 if ( IoctlDebug() ) {
1029 fprintf(stderr, "pioctl fs_GetFullPath SetCurrentDirectory(%s) failed: 0x%X\r\n",
1037 /* now get the absolute path to the current wdir in this drive */
1038 GetCurrentDirectory(sizeof(tpath), tpath);
1039 if (tpath[1] == ':')
1040 strcpy(outPathp, tpath + 2); /* skip drive letter */
1041 else if ( tpath[0] == '\\' && tpath[1] == '\\'||
1042 tpath[0] == '/' && tpath[1] == '/') {
1043 /* UNC path - strip off the server and sharename */
1045 for ( i=2,count=2; count < 4 && tpath[i]; i++ ) {
1046 if ( tpath[i] == '\\' || tpath[i] == '/' ) {
1050 if ( tpath[i] == 0 ) {
1051 strcpy(outPathp,"\\");
1053 strcpy(outPathp,&tpath[--i]);
1056 /* this should never happen */
1057 strcpy(outPathp, tpath);
1060 /* if there is a non-null name after the drive, append it */
1062 int len = (int)strlen(outPathp);
1063 if (outPathp[len-1] != '\\' && outPathp[len-1] != '/')
1064 strcat(outPathp, "\\");
1065 strcat(outPathp, firstp);
1068 /* finally, if necessary, switch back to our home drive letter */
1070 SetCurrentDirectory(origPath);
1073 for (p=outPathp ;*p; p++) {
1081 pioctl_int(char *pathp, long opcode, struct ViceIoctl *blobp, int follow, int is_utf8)
1083 fs_ioctlRequest_t preq;
1086 char fullPath[1000];
1090 code = GetIoctlHandle(pathp, &reqHandle);
1099 /* init the request structure */
1100 InitFSRequest(&preq);
1102 /* marshall the opcode, the path name and the input parameters */
1103 MarshallLong(&preq, opcode);
1104 /* when marshalling the path, remove the drive letter, since we already
1105 * used the drive letter to find the AFS daemon; we don't need it any more.
1106 * Eventually we'll expand relative path names here, too, since again, only
1107 * we understand those.
1110 code = fs_GetFullPath(pathp, fullPath, sizeof(fullPath));
1112 CloseHandle(reqHandle);
1117 strcpy(fullPath, "");
1120 MarshallString(&preq, fullPath, is_utf8);
1121 if (blobp->in_size) {
1122 if (blobp->in_size > sizeof(preq.data) - (preq.mp - preq.data)*sizeof(char)) {
1126 memcpy(preq.mp, blobp->in, blobp->in_size);
1127 preq.mp += blobp->in_size;
1130 /* now make the call */
1131 code = Transceive(reqHandle, &preq);
1133 CloseHandle(reqHandle);
1137 /* now unmarshall the return value */
1138 if (UnmarshallLong(&preq, &temp) != 0) {
1139 CloseHandle(reqHandle);
1144 CloseHandle(reqHandle);
1145 errno = CMtoUNIXerror(temp);
1146 if ( IoctlDebug() ) {
1148 fprintf(stderr, "pioctl temp != 0: 0x%X\r\n",temp);
1154 /* otherwise, unmarshall the output parameters */
1155 if (blobp->out_size) {
1156 temp = blobp->out_size;
1157 if (preq.nbytes < temp)
1159 memcpy(blobp->out, preq.mp, temp);
1160 blobp->out_size = temp;
1163 /* and return success */
1164 CloseHandle(reqHandle);
1169 pioctl_utf8(char * pathp, long opcode, struct ViceIoctl * blobp, int follow)
1171 return pioctl_int(pathp, opcode, blobp, follow, TRUE);
1175 pioctl(char * pathp, long opcode, struct ViceIoctl * blobp, int follow)
1177 return pioctl_int(pathp, opcode, blobp, follow, FALSE);