windows-pioctl-20041204
[openafs.git] / src / sys / pioctl_nt.c
index 0123f89..aa93298 100644 (file)
@@ -22,6 +22,8 @@ RCSID
 #include <string.h>
 #include <winioctl.h>
 #include <winsock2.h>
+#define SECURITY_WIN32
+#include <security.h>
 #include <nb30.h>
 
 #include <osi.h>
@@ -98,6 +100,30 @@ 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;
+}
+
 static long
 GetIoctlHandle(char *fileNamep, HANDLE * handlep)
 {
@@ -105,6 +131,15 @@ 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);
 
     if (fileNamep) {
         drivep = strchr(fileNamep, ':');
@@ -150,8 +185,8 @@ 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);
@@ -163,45 +198,147 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
                    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
                    FILE_FLAG_WRITE_THROUGH, NULL);
     fflush(stdout);
-       if (fh == INVALID_HANDLE_VALUE) {
-        HKEY hk;
-        char szUser[64] = "";
-        char szClient[MAX_PATH] = "";
-        char szPath[MAX_PATH] = "";
-        NETRESOURCE nr;
-        DWORD res;
-
-        if (GetLastError() != ERROR_DOWNGRADE_DETECTED)
-            return -1;
+    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%8X\r\n\t[%s]\r\n",
+                        tbuffer,gle,buf);
+            }
+        }
+#ifdef COMMENT
+        if (gle != ERROR_DOWNGRADE_DETECTED)
+            return -1;                                   
+#endif
 
         lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
-        sprintf(szPath, "\\\\%s", szClient);
 
-        /* We should probably be using GetUserNameEx() for this */
         if (RegOpenKey (HKEY_CURRENT_USER, 
-                        TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hk) == 0)
+                         TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hk) == 0)
         {
-            DWORD dwSize = sizeof(szUser);
             DWORD dwType = REG_SZ;
             RegQueryValueEx (hk, TEXT("Logon User Name"), NULL, &dwType, (PBYTE)szUser, &dwSize);
             RegCloseKey (hk);
         }
 
-        memset (&nr, 0x00, sizeof(NETRESOURCE));
-        nr.dwType=RESOURCETYPE_DISK;
-        nr.lpLocalName=0;
-        nr.lpRemoteName=szPath;
-        res = WNetAddConnection2(&nr,NULL,szUser,0);
-        if (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)
-            return -1;
-       }
+        if ( szUser[0] ) {
+            if ( ioctlDebug )
+                fprintf(stderr, "pioctl 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);
+                    }
+                    goto next_attempt;
+                }
+            }
+
+            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%8X\r\n\t[%s]\r\n",
+                                 tbuffer,gle,buf);
+                    }
+                }
+            }
+        }
+    }
+
+  next_attempt:
+    if ( fh == INVALID_HANDLE_VALUE ) {
+        if (GetUserNameEx(NameSamCompatible, szUser, &dwSize)) {
+            if ( ioctlDebug )
+                fprintf(stderr, "pioctl 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%8X\r\n\t[%s]\r\n",
+                                 tbuffer,gle,buf);
+                    }
+                }
+                return -1;
+            }
+        }
+    }
 
     /* return fh and success code */
     *handlep = fh;
@@ -213,19 +350,31 @@ Transceive(HANDLE handle, fs_ioctlRequest_t * reqp)
 {
     long rcount;
     long ioCount;
+    DWORD gle;
 
     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)) {
        /* 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;
     }
 
     reqp->nbytes = ioCount;    /* set # of bytes available */
@@ -248,6 +397,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;
     }
 
@@ -269,8 +421,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);
@@ -338,15 +493,19 @@ 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] == ':')
+        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++ ) {
@@ -366,10 +525,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 */
@@ -433,10 +592,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;
     }