afsifs-20050615
[openafs.git] / src / sys / pioctl_nt.c
index a03117c..333c3dc 100644 (file)
@@ -6,6 +6,30 @@
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
  */
+/* copyright (c) 2005
+ * the regents of the university of michigan
+ * all rights reserved
+ * 
+ * permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any purpose,
+ * so long as the name of the university of michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.  if
+ * the above copyright notice or any other identification of the
+ * university of michigan is included in any copy of any portion of
+ * this software, then the disclaimer below must also be included.
+ * 
+ * this software is provided as is, without representation from the
+ * university of michigan as to its fitness for any purpose, and without
+ * warranty by the university of michigan of any kind, either express
+ * or implied, including without limitation the implied warranties of
+ * merchantability and fitness for a particular purpose.  the regents
+ * of the university of michigan shall not be liable for any damages,
+ * including special, indirect, incidental, or consequential damages, 
+ * with respect to any claim arising out or in connection with the use
+ * of the software, even if it has been or is hereafter advised of the
+ * possibility of such damages.
+ */
 
 #include <afsconfig.h>
 #include <afs/param.h>
@@ -22,6 +46,8 @@ RCSID
 #include <string.h>
 #include <winioctl.h>
 #include <winsock2.h>
+#define SECURITY_WIN32
+#include <security.h>
 #include <nb30.h>
 
 #include <osi.h>
@@ -38,11 +64,14 @@ RCSID
 
 #include <smb.h>
 #include <pioctl_nt.h>
-
+#include <WINNT/afsreg.h>
 #include <lanahelper.h>
+#include <WINNT/afsrdr/kif.h>
 
-static char AFSConfigKeyName[] =
-    "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
+#include <loadfuncs-krb5.h>
+#include <krb5.h>
+
+static char AFSConfigKeyName[] = AFSREG_CLT_SVC_PARAM_SUBKEY;
 
 #define FS_IOCTLREQUEST_MAXSIZE        8192
 /* big structure for representing and storing an IOCTL request */
@@ -98,6 +127,202 @@ InitFSRequest(fs_ioctlRequest_t * rp)
     rp->nbytes = 0;
 }
 
+static BOOL
+IoctlDebug(void)
+{
+    static int init = 0;
+    static BOOL debug = 0;
+
+    if ( !init ) {
+        HKEY hk;
+
+        if (RegOpenKey (HKEY_LOCAL_MACHINE, 
+                         TEXT("Software\\OpenAFS\\Client"), &hk) == 0)
+        {
+            DWORD dwSize = sizeof(BOOL);
+            DWORD dwType = REG_DWORD;
+            RegQueryValueEx (hk, TEXT("IoctlDebug"), NULL, &dwType, (PBYTE)&debug, &dwSize);
+            RegCloseKey (hk);
+        }
+
+        init = 1;
+    }
+
+    return debug;
+}
+
+
+// krb5 functions
+DECL_FUNC_PTR(krb5_cc_default_name);
+DECL_FUNC_PTR(krb5_cc_set_default_name);
+DECL_FUNC_PTR(krb5_get_default_config_files);
+DECL_FUNC_PTR(krb5_free_config_files);
+DECL_FUNC_PTR(krb5_free_context);
+DECL_FUNC_PTR(krb5_get_default_realm);
+DECL_FUNC_PTR(krb5_free_default_realm);
+DECL_FUNC_PTR(krb5_init_context);
+DECL_FUNC_PTR(krb5_cc_default);
+DECL_FUNC_PTR(krb5_parse_name);
+DECL_FUNC_PTR(krb5_free_principal);
+DECL_FUNC_PTR(krb5_cc_close);
+DECL_FUNC_PTR(krb5_cc_get_principal);
+DECL_FUNC_PTR(krb5_build_principal);
+DECL_FUNC_PTR(krb5_c_random_make_octets);
+DECL_FUNC_PTR(krb5_get_init_creds_password);
+DECL_FUNC_PTR(krb5_free_cred_contents);
+DECL_FUNC_PTR(krb5_cc_resolve);
+DECL_FUNC_PTR(krb5_unparse_name);
+DECL_FUNC_PTR(krb5_free_unparsed_name);
+
+FUNC_INFO krb5_fi[] = {
+    MAKE_FUNC_INFO(krb5_cc_default_name),
+    MAKE_FUNC_INFO(krb5_cc_set_default_name),
+    MAKE_FUNC_INFO(krb5_get_default_config_files),
+    MAKE_FUNC_INFO(krb5_free_config_files),
+    MAKE_FUNC_INFO(krb5_free_context),
+    MAKE_FUNC_INFO(krb5_get_default_realm),
+    MAKE_FUNC_INFO(krb5_free_default_realm),
+    MAKE_FUNC_INFO(krb5_init_context),
+    MAKE_FUNC_INFO(krb5_cc_default),
+    MAKE_FUNC_INFO(krb5_parse_name),
+    MAKE_FUNC_INFO(krb5_free_principal),
+    MAKE_FUNC_INFO(krb5_cc_close),
+    MAKE_FUNC_INFO(krb5_cc_get_principal),
+    MAKE_FUNC_INFO(krb5_build_principal),
+    MAKE_FUNC_INFO(krb5_c_random_make_octets),
+    MAKE_FUNC_INFO(krb5_get_init_creds_password),
+    MAKE_FUNC_INFO(krb5_free_cred_contents),
+    MAKE_FUNC_INFO(krb5_cc_resolve),
+    MAKE_FUNC_INFO(krb5_unparse_name),
+    MAKE_FUNC_INFO(krb5_free_unparsed_name),
+    END_FUNC_INFO
+};
+
+static int
+LoadFuncs(
+    const char* dll_name,
+    FUNC_INFO fi[],
+    HINSTANCE* ph,  // [out, optional] - DLL handle
+    int* pindex,    // [out, optional] - index of last func loaded (-1 if none)
+    int cleanup,    // cleanup function pointers and unload on error
+    int go_on,      // continue loading even if some functions cannot be loaded
+    int silent      // do not pop-up a system dialog if DLL cannot be loaded
+    )
+{
+    HINSTANCE h;
+    int i, n, last_i;
+    int error = 0;
+    UINT em;
+
+    if (ph) *ph = 0;
+    if (pindex) *pindex = -1;
+
+    for (n = 0; fi[n].func_ptr_var; n++)
+        *(fi[n].func_ptr_var) = 0;
+
+    if (silent)
+        em = SetErrorMode(SEM_FAILCRITICALERRORS);
+    h = LoadLibrary(dll_name);
+    if (silent)
+        SetErrorMode(em);
+
+    if (!h)
+        return 0;
+
+    last_i = -1;
+    for (i = 0; (go_on || !error) && (i < n); i++)
+    {
+        void* p = (void*)GetProcAddress(h, fi[i].func_name);
+        if (!p)
+            error = 1;
+        else
+        {
+            last_i = i;
+            *(fi[i].func_ptr_var) = p;
+        }
+    }
+    if (pindex) *pindex = last_i;
+    if (error && cleanup && !go_on) {
+        for (i = 0; i < n; i++) {
+            *(fi[i].func_ptr_var) = 0;
+        }
+        FreeLibrary(h);
+        return 0;
+    }
+    if (ph) *ph = h;
+    if (error) return 0;
+    return 1;
+}
+
+#define KERB5DLL "krb5_32.dll"
+static BOOL
+IsKrb5Available()
+{
+    static HINSTANCE hKrb5DLL = 0;
+
+    if ( hKrb5DLL )
+        return TRUE;
+
+    hKrb5DLL = LoadLibrary(KERB5DLL);
+    if (hKrb5DLL) {
+        if (!LoadFuncs(KERB5DLL, krb5_fi, 0, 0, 1, 0, 0))
+        {
+            FreeLibrary(hKrb5DLL);
+            hKrb5DLL = 0;
+            return FALSE;
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static BOOL
+GetLSAPrincipalName(char * szUser, DWORD *dwSize)
+{
+    krb5_context   ctx = 0;
+    krb5_error_code code;
+    krb5_ccache mslsa_ccache=0;
+    krb5_principal princ = 0;
+    char * pname = 0;
+    BOOL success = 0;
+
+    if (!IsKrb5Available())
+        return FALSE;
+
+    if (code = pkrb5_init_context(&ctx))
+        goto cleanup;
+
+    if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
+        goto cleanup;
+
+    if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
+        goto cleanup;
+
+    if (code = pkrb5_unparse_name(ctx, princ, &pname))
+        goto cleanup;
+
+    if ( strlen(pname) < *dwSize ) {
+        strncpy(szUser, pname, *dwSize);
+        szUser[*dwSize-1] = '\0';
+        success = 1;
+    }
+    *dwSize = strlen(pname);
+
+  cleanup:
+    if (pname)
+        pkrb5_free_unparsed_name(ctx, pname);
+
+    if (princ)
+        pkrb5_free_principal(ctx, princ);
+
+    if (mslsa_ccache)
+        pkrb5_cc_close(ctx, mslsa_ccache);
+
+    if (ctx)
+        pkrb5_free_context(ctx);
+    return success;
+}
+
 static long
 GetIoctlHandle(char *fileNamep, HANDLE * handlep)
 {
@@ -105,7 +330,17 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
     char netbiosName[MAX_NB_NAME_LENGTH];
     char tbuffer[256]="";
     HANDLE fh;
-
+    HKEY hk;
+    char szUser[128] = "";
+    char szClient[MAX_PATH] = "";
+    char szPath[MAX_PATH] = "";
+    NETRESOURCE nr;
+    DWORD res;
+    DWORD ioctlDebug = IoctlDebug();
+    DWORD gle;
+    DWORD dwSize = sizeof(szUser);
+
+#ifndef AFSIFS
     if (fileNamep) {
         drivep = strchr(fileNamep, ':');
         if (drivep && (drivep - fileNamep) >= 1) {
@@ -150,21 +385,239 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
                 strcat(tbuffer, SMB_IOCTL_FILENAME_NOSLASH);
             }
         }
-       }
-       if (!tbuffer[0]) {
+    }
+    if (!tbuffer[0]) {
         /* No file name starting with drive colon specified, use UNC name */
         lana_GetNetbiosName(netbiosName,LANA_NETBIOS_NAME_FULL);
         sprintf(tbuffer,"\\\\%s\\all%s",netbiosName,SMB_IOCTL_FILENAME);
     }
+#else
+       sprintf(tbuffer,"\\\\.\\afscom\\ioctl");
+#endif 
 
     fflush(stdout);
     /* now open the file */
     fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
                    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
                    FILE_FLAG_WRITE_THROUGH, NULL);
-    fflush(stdout);
-    if (fh == INVALID_HANDLE_VALUE)
-       return -1;
+
+       fflush(stdout);
+
+#ifdef AFSIFS
+       if (fh == INVALID_HANDLE_VALUE) {
+               return -1;
+               }
+#endif
+       
+       if (fh == INVALID_HANDLE_VALUE) {
+        int  gonext = 0;
+
+        gle = GetLastError();
+        if (gle && ioctlDebug ) {
+            char buf[4096];
+
+            if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+                               NULL,
+                               gle,
+                               MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
+                               buf,
+                               4096,
+                               (va_list *) NULL
+                               ) )
+            {
+                fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
+                        tbuffer,gle,buf);
+            }
+        }
+
+        lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
+
+        if (RegOpenKey (HKEY_CURRENT_USER, 
+                         TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hk) == 0)
+        {
+            DWORD dwType = REG_SZ;
+            RegQueryValueEx (hk, TEXT("Logon User Name"), NULL, &dwType, (PBYTE)szUser, &dwSize);
+            RegCloseKey (hk);
+        }
+
+        if ( szUser[0] ) {
+            if ( ioctlDebug )
+                fprintf(stderr, "pioctl Explorer logon user: [%s]\r\n",szUser);
+
+            sprintf(szPath, "\\\\%s", szClient);
+            memset (&nr, 0x00, sizeof(NETRESOURCE));
+            nr.dwType=RESOURCETYPE_DISK;
+            nr.lpLocalName=0;
+            nr.lpRemoteName=szPath;
+            res = WNetAddConnection2(&nr,NULL,szUser,0);
+            if (res) {
+                if ( ioctlDebug ) {
+                    fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
+                             szPath,szUser,res);
+                }
+                gonext = 1;
+            }
+
+            sprintf(szPath, "\\\\%s\\all", szClient);
+            res = WNetAddConnection2(&nr,NULL,szUser,0);
+            if (res) {
+                if ( ioctlDebug ) {
+                    fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
+                             szPath,szUser,res);
+                }
+                gonext = 1;
+            }
+
+            if (gonext)
+                goto try_lsa_principal;
+
+            fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
+                             FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+                             FILE_FLAG_WRITE_THROUGH, NULL);
+            fflush(stdout);
+            if (fh == INVALID_HANDLE_VALUE) {
+                gle = GetLastError();
+                if (gle && ioctlDebug ) {
+                    char buf[4096];
+
+                    if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+                                        NULL,
+                                        gle,
+                                        MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
+                                        buf,
+                                        4096,
+                                        (va_list *) NULL
+                                        ) )
+                    {
+                        fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
+                                 tbuffer,gle,buf);
+                    }
+                }
+            }
+        }
+    }
+
+  try_lsa_principal:
+    if (fh == INVALID_HANDLE_VALUE) {
+        int  gonext = 0;
+
+        dwSize = sizeof(szUser);
+        if (GetLSAPrincipalName(szUser, &dwSize)) {
+            if ( ioctlDebug )
+                fprintf(stderr, "pioctl LSA Principal logon user: [%s]\r\n",szUser);
+
+            sprintf(szPath, "\\\\%s", szClient);
+            memset (&nr, 0x00, sizeof(NETRESOURCE));
+            nr.dwType=RESOURCETYPE_DISK;
+            nr.lpLocalName=0;
+            nr.lpRemoteName=szPath;
+            res = WNetAddConnection2(&nr,NULL,szUser,0);
+            if (res) {
+                if ( ioctlDebug ) {
+                    fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
+                             szPath,szUser,res);
+                }
+                gonext = 1;
+            }
+
+            sprintf(szPath, "\\\\%s\\all", szClient);
+            res = WNetAddConnection2(&nr,NULL,szUser,0);
+            if (res) {
+                if ( ioctlDebug ) {
+                    fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
+                             szPath,szUser,res);
+                }
+                gonext = 1;
+            }
+
+            if (gonext)
+                goto try_sam_compat;
+
+            fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
+                             FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+                             FILE_FLAG_WRITE_THROUGH, NULL);
+            fflush(stdout);
+            if (fh == INVALID_HANDLE_VALUE) {
+                gle = GetLastError();
+                if (gle && ioctlDebug ) {
+                    char buf[4096];
+
+                    if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+                                        NULL,
+                                        gle,
+                                        MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
+                                        buf,
+                                        4096,
+                                        (va_list *) NULL
+                                        ) )
+                    {
+                        fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
+                                 tbuffer,gle,buf);
+                    }
+                }
+            }
+        }
+    }
+
+  try_sam_compat:
+    if ( fh == INVALID_HANDLE_VALUE ) {
+        dwSize = sizeof(szUser);
+        if (GetUserNameEx(NameSamCompatible, szUser, &dwSize)) {
+            if ( ioctlDebug )
+                fprintf(stderr, "pioctl SamCompatible logon user: [%s]\r\n",szUser);
+
+            sprintf(szPath, "\\\\%s", szClient);
+            memset (&nr, 0x00, sizeof(NETRESOURCE));
+            nr.dwType=RESOURCETYPE_DISK;
+            nr.lpLocalName=0;
+            nr.lpRemoteName=szPath;
+            res = WNetAddConnection2(&nr,NULL,szUser,0);
+            if (res) {
+                if ( ioctlDebug ) {
+                    fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
+                             szPath,szUser,res);
+                }
+            }
+
+            sprintf(szPath, "\\\\%s\\all", szClient);
+            res = WNetAddConnection2(&nr,NULL,szUser,0);
+            if (res) {
+                if ( ioctlDebug ) {
+                    fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
+                             szPath,szUser,res);
+                }
+                return -1;
+            }
+
+            fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
+                             FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+                             FILE_FLAG_WRITE_THROUGH, NULL);
+            fflush(stdout);
+            if (fh == INVALID_HANDLE_VALUE) {
+                gle = GetLastError();
+                if (gle && ioctlDebug ) {
+                    char buf[4096];
+
+                    if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+                                        NULL,
+                                        gle,
+                                        MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
+                                        buf,
+                                        4096,
+                                        (va_list *) NULL
+                                        ) )
+                    {
+                        fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
+                                 tbuffer,gle,buf);
+                    }
+                }
+                return -1;
+            }
+        } else {
+            fprintf(stderr, "GetUserNameEx(NameSamCompatible) failed: 0x%X\r\n", GetLastError());
+            return -1;
+        }
+    }
 
     /* return fh and success code */
     *handlep = fh;
@@ -176,20 +629,45 @@ Transceive(HANDLE handle, fs_ioctlRequest_t * reqp)
 {
     long rcount;
     long ioCount;
+    DWORD gle;
+       char *data;
 
     rcount = reqp->mp - reqp->data;
-    if (rcount <= 0)
+    if (rcount <= 0) {
+        if ( IoctlDebug() )
+            fprintf(stderr, "pioctl Transceive rcount <= 0: %d\r\n",rcount);
        return EINVAL;          /* not supposed to happen */
+    }
 
-    if (!WriteFile(handle, reqp->data, rcount, &ioCount, NULL)) {
+#ifndef AFSIFS
+       if (!WriteFile(handle, reqp->data, rcount, &ioCount, NULL)) {
        /* failed to write */
-       return GetLastError();
+       gle = GetLastError();
+
+        if ( IoctlDebug() )
+            fprintf(stderr, "pioctl Transceive WriteFile failed: 0x%X\r\n",gle);
+        return gle;
     }
 
     if (!ReadFile(handle, reqp->data, sizeof(reqp->data), &ioCount, NULL)) {
        /* failed to read */
-       return GetLastError();
+       gle = GetLastError();
+
+        if ( IoctlDebug() )
+            fprintf(stderr, "pioctl Transceive ReadFile failed: 0x%X\r\n",gle);
+        return gle;
     }
+#else
+       /* ioctl completes as one operation, so copy input to a new buffer, and use as output buffer */
+       data = malloc(rcount);
+       memcpy(data, reqp->data, rcount);
+       if (!DeviceIoControl(handle, IOCTL_AFSRDR_IOCTL, data, rcount, reqp->data, sizeof(reqp->data), &ioCount, NULL))
+               {
+               free(data);
+               return GetLastError();
+               }
+       free(data);
+#endif
 
     reqp->nbytes = ioCount;    /* set # of bytes available */
     reqp->mp = reqp->data;     /* restart marshalling */
@@ -211,6 +689,9 @@ UnmarshallLong(fs_ioctlRequest_t * reqp, long *valp)
 {
     /* not enough data left */
     if (reqp->nbytes < 4) {
+        if ( IoctlDebug() )
+            fprintf(stderr, "pioctl UnmarshallLong reqp->nbytes < 4: %d\r\n",
+                     reqp->nbytes);
        return -1;
     }
 
@@ -232,8 +713,11 @@ MarshallString(fs_ioctlRequest_t * reqp, char *stringp)
        count = 1;
 
     /* watch for buffer overflow */
-    if ((reqp->mp - reqp->data) + count > sizeof(reqp->data))
+    if ((reqp->mp - reqp->data) + count > sizeof(reqp->data)) {
+        if ( IoctlDebug() )
+            fprintf(stderr, "pioctl MarshallString buffer overflow\r\n");
        return -1;
+    }
 
     if (stringp)
        memcpy(reqp->mp, stringp, count);
@@ -257,6 +741,34 @@ fs_GetFullPath(char *pathp, char *outPathp, long outSize)
     int pathHasDrive;
     int doSwitch;
     char newPath[3];
+       HANDLE rootDir;
+       wchar_t *wpath;
+       unsigned long length;
+
+#ifdef AFSIFS
+       if (!pathp)
+               return CM_ERROR_NOSUCHPATH;
+
+       //sprintf(tpath, "%c:\\", pathp[0]);
+       rootDir = CreateFile(pathp, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+       if (rootDir == INVALID_HANDLE_VALUE)
+               return CM_ERROR_NOSUCHPATH;
+
+       wpath = tpath;
+       length = 0;
+       if (!DeviceIoControl(rootDir, IOCTL_AFSRDR_GET_PATH, NULL, 0, wpath, 1000, &length, NULL))
+               {
+               CloseHandle(rootDir);
+               return CM_ERROR_NOSUCHPATH;
+               }
+       CloseHandle(rootDir);
+
+       code = WideCharToMultiByte(CP_UTF8, 0/*WC_NO_BEST_FIT_CHARS*/, wpath, length/sizeof(wchar_t), outPathp, outSize/sizeof(wchar_t), NULL, NULL);
+
+//    strcpy(outPathp, tpath);
+       return 0;
+#endif
+
 
     if (pathp[0] != 0 && pathp[1] == ':') {
        /* there's a drive letter there */
@@ -301,15 +813,20 @@ fs_GetFullPath(char *pathp, char *outPathp, long outSize)
        newPath[2] = 0;
        if (!SetCurrentDirectory(newPath)) {
            code = GetLastError();
+
+            if ( IoctlDebug() )
+                fprintf(stderr, "pioctl fs_GetFullPath SetCurrentDirectory(%s) failed: 0x%X\r\n",
+                         newPath, code);
            return code;
        }
     }
 
     /* now get the absolute path to the current wdir in this drive */
     GetCurrentDirectory(sizeof(tpath), tpath);
-       if (tpath[1] == ':')
-           strcpy(outPathp, tpath + 2);        /* skip drive letter */
-       else if ( tpath[0] == '\\' && tpath[1] == '\\') {
+    if (tpath[1] == ':')
+#ifndef AFSIFS
+        strcpy(outPathp, tpath + 2);   /* skip drive letter */
+    else if ( tpath[0] == '\\' && tpath[1] == '\\') {
         /* UNC path - strip off the server and sharename */
         int i, count;
         for ( i=2,count=2; count < 4 && tpath[i]; i++ ) {
@@ -322,6 +839,26 @@ fs_GetFullPath(char *pathp, char *outPathp, long outSize)
         } else {
             strcpy(outPathp,&tpath[--i]);
         }
+#else
+               {
+               HANDLE rootDir;
+
+        strcpy(outPathp, tpath);
+
+               sprintf(outPathp, "%c:\\", tpath[0]);
+               rootDir = CreateFile(outPathp, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+
+               if (!DeviceIoControl(rootDir, IOCTL_AFSRDR_GET_PATH, NULL, 0, absRoot_w, 100*sizeof(wchar_t), &length, NULL))
+                       {
+                       CloseHandle(rootDir);
+                       return CM_ERROR_NOSUCHPATH;
+                       }
+               CloseHandle(rootDir);
+
+               ifs_ConvertFileName(absRoot_w, length/sizeof(wchar_t), absRoot, 100);
+
+               }
+#endif
     } else {
         /* this should never happen */
         strcpy(outPathp, tpath);
@@ -329,10 +866,10 @@ fs_GetFullPath(char *pathp, char *outPathp, long outSize)
 
     /* if there is a non-null name after the drive, append it */
     if (*firstp != 0) {
-               int len = strlen(outPathp);
-               if (outPathp[len-1] != '\\' && outPathp[len-1] != '/') 
-                       strcat(outPathp, "\\");
-               strcat(outPathp, firstp);
+        int len = strlen(outPathp);
+        if (outPathp[len-1] != '\\' && outPathp[len-1] != '/') 
+            strcat(outPathp, "\\");
+        strcat(outPathp, firstp);
     }
 
     /* finally, if necessary, switch back to our home drive letter */
@@ -396,10 +933,16 @@ pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow)
     }
 
     /* now unmarshall the return value */
-    UnmarshallLong(&preq, &temp);
+    if (UnmarshallLong(&preq, &temp) != 0) {
+        CloseHandle(reqHandle);
+        return -1;
+    }
+
     if (temp != 0) {
        CloseHandle(reqHandle);
        errno = CMtoUNIXerror(temp);
+        if ( IoctlDebug() )
+            fprintf(stderr, "pioctl temp != 0: 0x%X\r\n",temp);
        return -1;
     }