This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
bump version for 5.29.1
[perl5.git] / win32 / vdir.h
index fb93205..9ff225e 100644 (file)
@@ -15,6 +15,7 @@
  * and one additional slot for a UNC name
  */
 const int driveCount = ('Z'-'A')+1+1;
+const int driveLetterCount = ('Z'-'A')+1;
 
 class VDir
 {
@@ -85,7 +86,7 @@ protected:
     {
        char *ptr = dirTableA[index];
        if (!ptr) {
-           /* simulate the existance of this drive */
+           /* simulate the existence of this drive */
            ptr = szLocalBufferA;
            ptr[0] = 'A' + index;
            ptr[1] = ':';
@@ -98,7 +99,7 @@ protected:
     {
        WCHAR *ptr = dirTableW[index];
        if (!ptr) {
-           /* simulate the existance of this drive */
+           /* simulate the existence of this drive */
            ptr = szLocalBufferW;
            ptr[0] = 'A' + index;
            ptr[1] = ':';
@@ -146,43 +147,21 @@ void VDir::Init(VDir* pDir, VMem *p)
     else {
        int bSave = bManageDirectory;
        DWORD driveBits = GetLogicalDrives();
-        OSVERSIONINFO osver;
-
-        memset(&osver, 0, sizeof(osver));
-        osver.dwOSVersionInfoSize = sizeof(osver);
-        GetVersionEx(&osver);
 
        bManageDirectory = 0;
-        if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
-            char szBuffer[MAX_PATH*driveCount];
-            if (GetLogicalDriveStringsA(sizeof(szBuffer), szBuffer)) {
-                char* pEnv = (char*)GetEnvironmentStringsA();
-                char* ptr = szBuffer;
-                for (index = 0; index < driveCount; ++index) {
-                    if (driveBits & (1<<index)) {
-                        ptr += SetDirA(ptr, index) + 1;
-                        FromEnvA(pEnv, index);
-                    }
+        WCHAR szBuffer[MAX_PATH*driveCount];
+        if (GetLogicalDriveStringsW(sizeof(szBuffer), szBuffer)) {
+            WCHAR* pEnv = GetEnvironmentStringsW();
+            WCHAR* ptr = szBuffer;
+            for (index = 0; index < driveCount; ++index) {
+                if (driveBits & (1<<index)) {
+                    ptr += SetDirW(ptr, index) + 1;
+                    FromEnvW(pEnv, index);
                 }
-                FreeEnvironmentStringsA(pEnv);
             }
-            SetDefaultA(".");
-        }
-        else { /* Windows NT or later */
-            WCHAR szBuffer[MAX_PATH*driveCount];
-            if (GetLogicalDriveStringsW(sizeof(szBuffer), szBuffer)) {
-                WCHAR* pEnv = GetEnvironmentStringsW();
-                WCHAR* ptr = szBuffer;
-                for (index = 0; index < driveCount; ++index) {
-                    if (driveBits & (1<<index)) {
-                        ptr += SetDirW(ptr, index) + 1;
-                        FromEnvW(pEnv, index);
-                    }
-                }
-                FreeEnvironmentStringsW(pEnv);
-            }
-            SetDefaultW(L".");
+            FreeEnvironmentStringsW(pEnv);
         }
+        SetDefaultW(L".");
        bManageDirectory = bSave;
   }
 }
@@ -224,7 +203,8 @@ int VDir::SetDirA(char const *pPath, int index)
 void VDir::FromEnvA(char *pEnv, int index)
 {   /* gets the directory for index from the environment variable. */
     while (*pEnv != '\0') {
-       if ((pEnv[0] == '=') && (DriveIndex(pEnv[1]) == index)) {
+       if ((pEnv[0] == '=') && (DriveIndex(pEnv[1]) == index)
+            && pEnv[2] == ':' && pEnv[3] == '=') {
            SetDirA(&pEnv[4], index);
            break;
        }
@@ -236,7 +216,8 @@ void VDir::FromEnvA(char *pEnv, int index)
 void VDir::FromEnvW(WCHAR *pEnv, int index)
 {   /* gets the directory for index from the environment variable. */
     while (*pEnv != '\0') {
-       if ((pEnv[0] == '=') && (DriveIndex((char)pEnv[1]) == index)) {
+       if ((pEnv[0] == '=') && (DriveIndex((char)pEnv[1]) == index)
+            && pEnv[2] == ':' && pEnv[3] == '=') {
            SetDirW(&pEnv[4], index);
            break;
        }
@@ -316,7 +297,7 @@ inline void DoGetFullPathNameA(char* lpBuffer, DWORD dwSize, char* Dest)
 
     /*
      * On WinNT GetFullPathName does not fail, (or at least always
-     * succeeds when the drive is valid) WinNT does set *Dest to Nullch
+     * succeeds when the drive is valid) WinNT does set *Dest to NULL
      * On Win98 GetFullPathName will set last error if it fails, but
      * does not touch *Dest
      */
@@ -405,6 +386,7 @@ char *VDir::MapPathA(const char *pInName)
      * possiblities -- relative path or absolute path with or without drive letter
      * OR UNC name
      */
+    int driveIndex;
     char szBuffer[(MAX_PATH+1)*2];
     char szlBuf[MAX_PATH+1];
     int length = strlen(pInName);
@@ -424,15 +406,18 @@ char *VDir::MapPathA(const char *pInName)
     }
     /* strlen(pInName) is now <= MAX_PATH */
 
-    if (pInName[1] == ':') {
+    if (length > 1 && pInName[1] == ':') {
        /* has drive letter */
-       if (IsPathSep(pInName[2])) {
+       if (length > 2 && IsPathSep(pInName[2])) {
            /* absolute with drive letter */
            DoGetFullPathNameA((char*)pInName, sizeof(szLocalBufferA), szLocalBufferA);
        }
        else {
            /* relative path with drive letter */
-           strcpy(szBuffer, GetDirA(DriveIndex(*pInName)));
+            driveIndex = DriveIndex(*pInName);
+            if (driveIndex < 0 || driveIndex >= driveLetterCount)
+                return (char *)pInName;
+           strcpy(szBuffer, GetDirA(driveIndex));
            strcat(szBuffer, &pInName[2]);
            if(strlen(szBuffer) > MAX_PATH)
                szBuffer[MAX_PATH] = '\0';
@@ -442,7 +427,7 @@ char *VDir::MapPathA(const char *pInName)
     }
     else {
        /* no drive letter */
-       if (IsPathSep(pInName[1]) && IsPathSep(pInName[0])) {
+       if (length > 1 && IsPathSep(pInName[1]) && IsPathSep(pInName[0])) {
            /* UNC name */
            DoGetFullPathNameA((char*)pInName, sizeof(szLocalBufferA), szLocalBufferA);
        }
@@ -544,7 +529,7 @@ inline void DoGetFullPathNameW(WCHAR* lpBuffer, DWORD dwSize, WCHAR* Dest)
 
     /*
      * On WinNT GetFullPathName does not fail, (or at least always
-     * succeeds when the drive is valid) WinNT does set *Dest to Nullch
+     * succeeds when the drive is valid) WinNT does set *Dest to NULL
      * On Win98 GetFullPathName will set last error if it fails, but
      * does not touch *Dest
      */
@@ -633,6 +618,7 @@ WCHAR* VDir::MapPathW(const WCHAR *pInName)
      * possiblities -- relative path or absolute path with or without drive letter
      * OR UNC name
      */
+    int driveIndex;
     WCHAR szBuffer[(MAX_PATH+1)*2];
     WCHAR szlBuf[MAX_PATH+1];
     int length = wcslen(pInName);
@@ -652,7 +638,7 @@ WCHAR* VDir::MapPathW(const WCHAR *pInName)
     }
     /* strlen(pInName) is now <= MAX_PATH */
 
-    if (pInName[1] == ':') {
+    if (length > 1 && pInName[1] == ':') {
        /* has drive letter */
        if (IsPathSep(pInName[2])) {
            /* absolute with drive letter */
@@ -660,7 +646,10 @@ WCHAR* VDir::MapPathW(const WCHAR *pInName)
        }
        else {
            /* relative path with drive letter */
-           wcscpy(szBuffer, GetDirW(DriveIndex((char)*pInName)));
+            driveIndex = DriveIndex(*pInName);
+            if (driveIndex < 0 || driveIndex >= driveLetterCount)
+                return (WCHAR *)pInName;
+           wcscpy(szBuffer, GetDirW(driveIndex));
            wcscat(szBuffer, &pInName[2]);
            if(wcslen(szBuffer) > MAX_PATH)
                szBuffer[MAX_PATH] = '\0';
@@ -670,7 +659,7 @@ WCHAR* VDir::MapPathW(const WCHAR *pInName)
     }
     else {
        /* no drive letter */
-       if (IsPathSep(pInName[1]) && IsPathSep(pInName[0])) {
+       if (length > 1 && IsPathSep(pInName[1]) && IsPathSep(pInName[0])) {
            /* UNC name */
            DoGetFullPathNameW((WCHAR*)pInName, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW);
        }