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 10119ea..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
 {
@@ -34,47 +35,48 @@ public:
     inline char* GetCurrentDirectoryA(int dwBufSize, char *lpBuffer)
     {
        char* ptr = dirTableA[nDefault];
-       while (dwBufSize--)
+       while (--dwBufSize)
        {
            if ((*lpBuffer++ = *ptr++) == '\0')
                break;
        }
-       return lpBuffer;
+        *lpBuffer = '\0';
+       return /* unused */ NULL;
     };
     inline WCHAR* GetCurrentDirectoryW(int dwBufSize, WCHAR *lpBuffer)
     {
        WCHAR* ptr = dirTableW[nDefault];
-       while (dwBufSize--)
+       while (--dwBufSize)
        {
            if ((*lpBuffer++ = *ptr++) == '\0')
                break;
        }
-       return lpBuffer;
+        *lpBuffer = '\0';
+       return /* unused */ NULL;
     };
 
-
     DWORD CalculateEnvironmentSpace(void);
     LPSTR BuildEnvironmentSpace(LPSTR lpStr);
 
 protected:
     int SetDirA(char const *pPath, int index);
+    int SetDirW(WCHAR const *pPath, int index);
     void FromEnvA(char *pEnv, int index);
+    void FromEnvW(WCHAR *pEnv, int index);
+
     inline const char *GetDefaultDirA(void)
     {
        return dirTableA[nDefault];
     };
-
     inline void SetDefaultDirA(char const *pPath, int index)
     {
        SetDirA(pPath, index);
        nDefault = index;
     };
-    int SetDirW(WCHAR const *pPath, int index);
     inline const WCHAR *GetDefaultDirW(void)
     {
        return dirTableW[nDefault];
     };
-
     inline void SetDefaultDirW(WCHAR const *pPath, int index)
     {
        SetDirW(pPath, index);
@@ -84,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] = ':';
@@ -97,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] = ':';
@@ -134,9 +136,6 @@ VDir::VDir(int bManageDir /* = 1 */)
 void VDir::Init(VDir* pDir, VMem *p)
 {
     int index;
-    DWORD driveBits;
-    int nSave;
-    char szBuffer[MAX_PATH*driveCount];
 
     pMem = p;
     if (pDir) {
@@ -146,23 +145,25 @@ void VDir::Init(VDir* pDir, VMem *p)
        nDefault = pDir->GetDefault();
     }
     else {
-       nSave = bManageDirectory;
+       int bSave = bManageDirectory;
+       DWORD driveBits = GetLogicalDrives();
+
        bManageDirectory = 0;
-       driveBits = GetLogicalDrives();
-       if (GetLogicalDriveStrings(sizeof(szBuffer), szBuffer)) {
-           char* pEnv = (char*)GetEnvironmentStrings();
-           char* ptr = szBuffer;
-           for (index = 0; index < driveCount; ++index) {
-               if (driveBits & (1<<index)) {
-                   ptr += SetDirA(ptr, index) + 1;
-                   FromEnvA(pEnv, index);
-               }
-           }
-           FreeEnvironmentStrings(pEnv);
-       }
-       SetDefaultA(".");
-       bManageDirectory = nSave;
-    }
+        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".");
+       bManageDirectory = bSave;
+  }
 }
 
 int VDir::SetDirA(char const *pPath, int index)
@@ -202,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;
        }
@@ -211,6 +213,19 @@ 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)
+            && pEnv[2] == ':' && pEnv[3] == '=') {
+           SetDirW(&pEnv[4], index);
+           break;
+       }
+       else
+           pEnv += wcslen(pEnv)+1;
+    }
+}
+
 void VDir::SetDefaultA(char const *pDefault)
 {
     char szBuffer[MAX_PATH+1];
@@ -227,13 +242,13 @@ void VDir::SetDefaultA(char const *pDefault)
 int VDir::SetDirW(WCHAR const *pPath, int index)
 {
     WCHAR chr, *ptr;
-    char szBuffer[MAX_PATH+1];
     int length = 0;
     if (index < driveCount && pPath != NULL) {
        length = wcslen(pPath);
        pMem->Free(dirTableW[index]);
        ptr = dirTableW[index] = (WCHAR*)pMem->Malloc((length+2)*2);
        if (ptr != NULL) {
+            char *ansi;
            wcscpy(ptr, pPath);
            ptr += length-1;
            chr = *ptr++;
@@ -241,13 +256,14 @@ int VDir::SetDirW(WCHAR const *pPath, int index)
                *ptr++ = '\\';
                *ptr = '\0';
            }
-           WideCharToMultiByte(CP_ACP, 0, dirTableW[index], -1, szBuffer, sizeof(szBuffer), NULL, NULL);
-           length = strlen(szBuffer);
+            ansi = win32_ansipath(dirTableW[index]);
+           length = strlen(ansi);
            pMem->Free(dirTableA[index]);
            dirTableA[index] = (char*)pMem->Malloc(length+1);
            if (dirTableA[index] != NULL) {
-               strcpy(dirTableA[index], szBuffer);
+               strcpy(dirTableA[index], ansi);
            }
+            win32_free(ansi);
        }
     }
 
@@ -281,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
      */
@@ -370,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);
@@ -389,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';
@@ -407,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);
        }
@@ -509,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
      */
@@ -598,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);
@@ -617,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 */
@@ -625,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';
@@ -635,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);
        }