windows-pioctl-global-auto-mapper-20081125
[openafs.git] / src / sys / pioctl_nt.c
index 4bcc433..0460e26 100644 (file)
@@ -397,14 +397,121 @@ GetLSAPrincipalName(char * szUser, DWORD *dwSize)
     return success;
 }
 
+static BOOL
+DriveIsMappedToAFS(char *drivestr, char *NetbiosName)
+{
+    DWORD dwResult, dwResultEnum;
+    HANDLE hEnum;
+    DWORD cbBuffer = 16384;     // 16K is a good size
+    DWORD cEntries = -1;        // enumerate all possible entries
+    LPNETRESOURCE lpnrLocal;    // pointer to enumerated structures
+    DWORD i;
+    BOOL  bIsAFS = FALSE;
+
+    //
+    // Call the WNetOpenEnum function to begin the enumeration.
+    //
+    dwResult = WNetOpenEnum(RESOURCE_CONNECTED,
+                            RESOURCETYPE_DISK,
+                            RESOURCEUSAGE_ALL,
+                            NULL,       // NULL first time the function is called
+                            &hEnum);    // handle to the resource
+
+    if (dwResult != NO_ERROR)
+        return FALSE;
+
+    //
+    // Call the GlobalAlloc function to allocate resources.
+    //
+    lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
+    if (lpnrLocal == NULL)
+        return FALSE;
+
+    do {
+        //
+        // Initialize the buffer.
+        //
+        ZeroMemory(lpnrLocal, cbBuffer);
+        //
+        // Call the WNetEnumResource function to continue
+        //  the enumeration.
+        //
+        cEntries = -1;
+        dwResultEnum = WNetEnumResource(hEnum,          // resource handle
+                                        &cEntries,      // defined locally as -1
+                                        lpnrLocal,      // LPNETRESOURCE
+                                        &cbBuffer);     // buffer size
+        //
+        // If the call succeeds, loop through the structures.
+        //
+        if (dwResultEnum == NO_ERROR) {
+            for (i = 0; i < cEntries; i++) {
+                if (lpnrLocal[i].lpLocalName &&
+                    toupper(lpnrLocal[i].lpLocalName[0]) == toupper(drivestr[0])) {
+                    //
+                    // Skip the two backslashes at the start of the UNC device name
+                    //
+                    if ( _strnicmp( &(lpnrLocal[i].lpRemoteName[2]), NetbiosName, strlen(NetbiosName)) == 0 )
+                    {
+                        bIsAFS = TRUE;
+                        break;
+                    }
+                }
+            }
+        }
+        // Process errors.
+        //
+        else if (dwResultEnum != ERROR_NO_MORE_ITEMS)
+            break;
+    }
+    while (dwResultEnum != ERROR_NO_MORE_ITEMS);
+    
+    //
+    // Call the GlobalFree function to free the memory.
+    //
+    GlobalFree((HGLOBAL) lpnrLocal);
+    //
+    // Call WNetCloseEnum to end the enumeration.
+    //
+    dwResult = WNetCloseEnum(hEnum);
+
+    return bIsAFS;
+}
+
+static BOOL
+DriveIsGlobalAutoMapped(char *drivestr)
+{
+    DWORD dwResult;
+    HKEY hKey;
+    DWORD dwSubMountSize;
+    char szSubMount[260];
+    DWORD dwType;
+
+    dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
+                            AFSREG_CLT_SVC_PARAM_SUBKEY "\\GlobalAutoMapper", 
+                            0, KEY_QUERY_VALUE, &hKey);
+    if (dwResult != ERROR_SUCCESS)
+        return FALSE;
+
+    dwSubMountSize = sizeof(szSubMount);
+    dwType = REG_SZ;
+    dwResult = RegQueryValueEx(hKey, drivestr, 0, &dwType, szSubMount, &dwSubMountSize);
+    RegCloseKey(hKey);
+
+    if (dwResult == ERROR_SUCCESS && dwType == REG_SZ)
+        return TRUE;
+    else
+        return FALSE;
+}
+
 static long
 GetIoctlHandle(char *fileNamep, HANDLE * handlep)
 {
-    char *drivep;
+    char *drivep = NULL;
     char netbiosName[MAX_NB_NAME_LENGTH];
     DWORD CurrentState = 0;
     char  HostName[64] = "";
-    char tbuffer[256]="";
+    char tbuffer[MAX_PATH]="";
     HANDLE fh;
     HKEY hk;
     char szUser[128] = "";
@@ -415,6 +522,8 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
     DWORD ioctlDebug = IoctlDebug();
     DWORD gle;
     DWORD dwSize = sizeof(szUser);
+    int saveerrno;
+    UINT driveType;
 
     memset(HostName, '\0', sizeof(HostName));
     gethostname(HostName, sizeof(HostName));
@@ -423,12 +532,32 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
        CurrentState != SERVICE_RUNNING)
        return -1;
 
+    // Populate the Netbios Name
+    lana_GetNetbiosName(netbiosName,LANA_NETBIOS_NAME_FULL);
+
     if (fileNamep) {
         drivep = strchr(fileNamep, ':');
         if (drivep && (drivep - fileNamep) >= 1) {
             tbuffer[0] = *(drivep - 1);
             tbuffer[1] = ':';
-            strcpy(tbuffer + 2, SMB_IOCTL_FILENAME);
+            tbuffer[2] = '\0';
+
+            driveType = GetDriveType(tbuffer);
+            switch (driveType) {
+            case DRIVE_UNKNOWN:
+            case DRIVE_REMOTE:
+                if (DriveIsMappedToAFS(tbuffer, netbiosName) ||
+                    DriveIsGlobalAutoMapped(tbuffer))
+                    strcpy(&tbuffer[2], SMB_IOCTL_FILENAME);
+                else 
+                    return -1;
+                break;
+            default:
+                if (DriveIsGlobalAutoMapped(tbuffer))
+                    strcpy(&tbuffer[2], SMB_IOCTL_FILENAME);
+                else 
+                    return -1;
+            }
         } else if (fileNamep[0] == fileNamep[1] && 
                   (fileNamep[0] == '\\' || fileNamep[0] == '/'))
         {
@@ -446,13 +575,30 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
             tbuffer[i] = 0;
             strcat(tbuffer, SMB_IOCTL_FILENAME);
         } else {
-            char curdir[256]="";
+            char curdir[MAX_PATH]="";
 
             GetCurrentDirectory(sizeof(curdir), curdir);
             if ( curdir[1] == ':' ) {
                 tbuffer[0] = curdir[0];
                 tbuffer[1] = ':';
-                strcpy(tbuffer + 2, SMB_IOCTL_FILENAME);
+                tbuffer[2] = '\0';
+
+                driveType = GetDriveType(tbuffer);
+                switch (driveType) {
+                case DRIVE_UNKNOWN:
+                case DRIVE_REMOTE:
+                    if (DriveIsMappedToAFS(tbuffer, netbiosName) ||
+                        DriveIsGlobalAutoMapped(tbuffer))
+                        strcpy(&tbuffer[2], SMB_IOCTL_FILENAME);
+                    else 
+                        return -1;
+                    break;
+                default:
+                    if (DriveIsGlobalAutoMapped(tbuffer))
+                        strcpy(&tbuffer[2], SMB_IOCTL_FILENAME);
+                    else 
+                        return -1;
+                }
             } else if (curdir[0] == curdir[1] &&
                        (curdir[0] == '\\' || curdir[0] == '/')) 
             {
@@ -474,7 +620,6 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
     }
     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);
     }
 
@@ -492,7 +637,8 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
         gle = GetLastError();
         if (gle && ioctlDebug ) {
             char buf[4096];
-
+            
+            saveerrno = errno;
             if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
                                NULL,
                                gle,
@@ -505,6 +651,7 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
                 fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
                         tbuffer,gle,buf);
             }
+            errno = saveerrno;
         }
 
         lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
@@ -518,9 +665,11 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
         }
 
         if ( szUser[0] ) {
-            if ( ioctlDebug )
+            if ( ioctlDebug ) {
+                saveerrno = errno;
                 fprintf(stderr, "pioctl Explorer logon user: [%s]\r\n",szUser);
-
+                errno = saveerrno;
+            }
             sprintf(szPath, "\\\\%s", szClient);
             memset (&nr, 0x00, sizeof(NETRESOURCE));
             nr.dwType=RESOURCETYPE_DISK;
@@ -529,8 +678,10 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
             res = WNetAddConnection2(&nr,NULL,szUser,0);
             if (res) {
                 if ( ioctlDebug ) {
+                    saveerrno = errno;
                     fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
                              szPath,szUser,res);
+                    errno = saveerrno;
                 }
                 gonext = 1;
             }
@@ -539,8 +690,10 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
             res = WNetAddConnection2(&nr,NULL,szUser,0);
             if (res) {
                 if ( ioctlDebug ) {
+                    saveerrno = errno;
                     fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
                              szPath,szUser,res);
+                    errno = saveerrno;
                 }
                 gonext = 1;
             }
@@ -557,6 +710,7 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
                 if (gle && ioctlDebug ) {
                     char buf[4096];
 
+                    saveerrno = errno;
                     if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
                                         NULL,
                                         gle,
@@ -569,6 +723,7 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
                         fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
                                  tbuffer,gle,buf);
                     }
+                    errno = saveerrno;
                 }
             }
         }
@@ -580,9 +735,11 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
 
         dwSize = sizeof(szUser);
         if (GetLSAPrincipalName(szUser, &dwSize)) {
-            if ( ioctlDebug )
+            if ( ioctlDebug ) {
+                saveerrno = errno;
                 fprintf(stderr, "pioctl LSA Principal logon user: [%s]\r\n",szUser);
-
+                errno = saveerrno;
+            }
             sprintf(szPath, "\\\\%s", szClient);
             memset (&nr, 0x00, sizeof(NETRESOURCE));
             nr.dwType=RESOURCETYPE_DISK;
@@ -591,8 +748,10 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
             res = WNetAddConnection2(&nr,NULL,szUser,0);
             if (res) {
                 if ( ioctlDebug ) {
+                    saveerrno = errno;
                     fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
                              szPath,szUser,res);
+                    errno = saveerrno;
                 }
                 gonext = 1;
             }
@@ -601,8 +760,10 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
             res = WNetAddConnection2(&nr,NULL,szUser,0);
             if (res) {
                 if ( ioctlDebug ) {
+                    saveerrno = errno;
                     fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
                              szPath,szUser,res);
+                    errno = saveerrno;
                 }
                 gonext = 1;
             }
@@ -619,6 +780,7 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
                 if (gle && ioctlDebug ) {
                     char buf[4096];
 
+                    saveerrno = errno;
                     if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
                                         NULL,
                                         gle,
@@ -631,6 +793,8 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
                         fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
                                  tbuffer,gle,buf);
                     }
+                    errno = saveerrno;
+
                 }
             }
         }
@@ -640,9 +804,11 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
     if ( fh == INVALID_HANDLE_VALUE ) {
         dwSize = sizeof(szUser);
         if (GetUserNameEx(NameSamCompatible, szUser, &dwSize)) {
-            if ( ioctlDebug )
+            if ( ioctlDebug ) {
+                saveerrno = errno;
                 fprintf(stderr, "pioctl SamCompatible logon user: [%s]\r\n",szUser);
-
+                errno = saveerrno;
+            }
             sprintf(szPath, "\\\\%s", szClient);
             memset (&nr, 0x00, sizeof(NETRESOURCE));
             nr.dwType=RESOURCETYPE_DISK;
@@ -651,8 +817,10 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
             res = WNetAddConnection2(&nr,NULL,szUser,0);
             if (res) {
                 if ( ioctlDebug ) {
+                    saveerrno = errno;
                     fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
                              szPath,szUser,res);
+                    errno = saveerrno;
                 }
             }
 
@@ -660,8 +828,10 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
             res = WNetAddConnection2(&nr,NULL,szUser,0);
             if (res) {
                 if ( ioctlDebug ) {
+                    saveerrno = errno;
                     fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
                              szPath,szUser,res);
+                    errno = saveerrno;
                 }
                 return -1;
             }
@@ -675,6 +845,7 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
                 if (gle && ioctlDebug ) {
                     char buf[4096];
 
+                    saveerrno = errno;
                     if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
                                         NULL,
                                         gle,
@@ -687,6 +858,7 @@ GetIoctlHandle(char *fileNamep, HANDLE * handlep)
                         fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
                                  tbuffer,gle,buf);
                     }
+                    errno = saveerrno;
                 }
                 return -1;
             }
@@ -707,11 +879,16 @@ Transceive(HANDLE handle, fs_ioctlRequest_t * reqp)
     long rcount;
     long ioCount;
     DWORD gle;
+    DWORD ioctlDebug = IoctlDebug();
+    int save;
 
     rcount = (long)(reqp->mp - reqp->data);
     if (rcount <= 0) {
-        if ( IoctlDebug() )
+        if ( ioctlDebug ) {
+            save = errno;
             fprintf(stderr, "pioctl Transceive rcount <= 0: %d\r\n",rcount);
+            errno = save;
+        }
        return EINVAL;          /* not supposed to happen */
     }
 
@@ -719,8 +896,11 @@ Transceive(HANDLE handle, fs_ioctlRequest_t * reqp)
        /* failed to write */
        gle = GetLastError();
 
-        if ( IoctlDebug() )
+        if ( ioctlDebug ) {
+            save = errno;
             fprintf(stderr, "pioctl Transceive WriteFile failed: 0x%X\r\n",gle);
+            errno = save;
+        }
         return gle;
     }
 
@@ -728,8 +908,11 @@ Transceive(HANDLE handle, fs_ioctlRequest_t * reqp)
        /* failed to read */
        gle = GetLastError();
 
-        if ( IoctlDebug() )
+        if ( ioctlDebug ) {
+            save = errno;
             fprintf(stderr, "pioctl Transceive ReadFile failed: 0x%X\r\n",gle);
+            errno = save;
+        }
         return gle;
     }
 
@@ -751,11 +934,16 @@ MarshallLong(fs_ioctlRequest_t * reqp, long val)
 static long
 UnmarshallLong(fs_ioctlRequest_t * reqp, long *valp)
 {
+    int save;
+
     /* not enough data left */
     if (reqp->nbytes < 4) {
-        if ( IoctlDebug() )
+        if ( IoctlDebug() ) {
+            save = errno;
             fprintf(stderr, "pioctl UnmarshallLong reqp->nbytes < 4: %d\r\n",
                      reqp->nbytes);
+            errno = save;
+        }
        return -1;
     }
 
@@ -770,6 +958,7 @@ static long
 MarshallString(fs_ioctlRequest_t * reqp, char *stringp, int is_utf8)
 {
     int count;
+    int save;
 
     if (stringp)
        count = (int)strlen(stringp) + 1;/* space required including null */
@@ -782,8 +971,11 @@ MarshallString(fs_ioctlRequest_t * reqp, char *stringp, int is_utf8)
 
     /* watch for buffer overflow */
     if ((reqp->mp - reqp->data) + count > sizeof(reqp->data)) {
-        if ( IoctlDebug() )
+        if ( IoctlDebug() ) {
+            save = errno;
             fprintf(stderr, "pioctl MarshallString buffer overflow\r\n");
+            errno = save;
+        }
        return -1;
     }
 
@@ -816,6 +1008,7 @@ fs_GetFullPath(char *pathp, char *outPathp, long outSize)
     int doSwitch;
     char newPath[3];
     char * p;
+    int save;
 
     if (pathp[0] != 0 && pathp[1] == ':') {
        /* there's a drive letter there */
@@ -870,9 +1063,12 @@ fs_GetFullPath(char *pathp, char *outPathp, long outSize)
        if (!SetCurrentDirectory(newPath)) {
            code = GetLastError();
 
-            if ( IoctlDebug() )
+            if ( IoctlDebug() ) {
+                save = errno;
                 fprintf(stderr, "pioctl fs_GetFullPath SetCurrentDirectory(%s) failed: 0x%X\r\n",
                          newPath, code);
+                errno = save;
+            }
            return code;
        }
     }
@@ -928,6 +1124,7 @@ pioctl_int(char *pathp, long opcode, struct ViceIoctl *blobp, int follow, int is
     long temp;
     char fullPath[1000];
     HANDLE reqHandle;
+    int save;
 
     code = GetIoctlHandle(pathp, &reqHandle);
     if (code) {
@@ -985,8 +1182,11 @@ pioctl_int(char *pathp, long opcode, struct ViceIoctl *blobp, int follow, int is
     if (temp != 0) {
        CloseHandle(reqHandle);
        errno = CMtoUNIXerror(temp);
-        if ( IoctlDebug() )
+        if ( IoctlDebug() ) {
+            save = errno;
             fprintf(stderr, "pioctl temp != 0: 0x%X\r\n",temp);
+            errno = save;
+        }
        return -1;
     }