From: Gurusamy Sarathy <gsar@cpan.org>
Date: Thu, 10 Feb 2000 01:08:01 +0000 (+0000)
Subject: windows bugfixes for virtual directories under USE_ITHREADS:
X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=e2694c95595459ec14c9aadb4c537ffb639f1a55;p=p5sagit%2Fp5-mst-13.2.git

windows bugfixes for virtual directories under USE_ITHREADS:
allows path mapping to unknown devices to work properly;
special file names like CONOUT$ can be opened with sysopen()
again

p4raw-id: //depot/perl@5057
---

diff --git a/win32/vdir.h b/win32/vdir.h
index 50822a7..df9a10b 100644
--- a/win32/vdir.h
+++ b/win32/vdir.h
@@ -25,14 +25,6 @@ public:
     WCHAR* MapPathW(const WCHAR *pInName);
     int SetCurrentDirectoryA(char *lpBuffer);
     int SetCurrentDirectoryW(WCHAR *lpBuffer);
-    inline const char *GetDirA(int index)
-    {
-	return dirTableA[index];
-    };
-    inline const WCHAR *GetDirW(int index)
-    {
-	return dirTableW[index];
-    };
     inline int GetDefault(void) { return nDefault; };
 
     inline char* GetCurrentDirectoryA(int dwBufSize, char *lpBuffer)
@@ -84,6 +76,32 @@ protected:
 	SetDirW(pPath, index);
 	nDefault = index;
     };
+    inline const char *GetDirA(int index)
+    {
+	char *ptr = dirTableA[index];
+	if (!ptr) {
+	    /* simulate the existance of this drive */
+	    ptr = szLocalBufferA;
+	    ptr[0] = 'A' + index;
+	    ptr[1] = ':';
+	    ptr[2] = '\\';
+	    ptr[3] = 0;
+	}
+	return ptr;
+    };
+    inline const WCHAR *GetDirW(int index)
+    {
+	WCHAR *ptr = dirTableW[index];
+	if (!ptr) {
+	    /* simulate the existance of this drive */
+	    ptr = szLocalBufferW;
+	    ptr[0] = 'A' + index;
+	    ptr[1] = ':';
+	    ptr[2] = '\\';
+	    ptr[3] = 0;
+	}
+	return ptr;
+    };
 
     inline int DriveIndex(char chr)
     {
@@ -265,6 +283,82 @@ inline void DoGetFullPathNameA(char* lpBuffer, DWORD dwSize, char* Dest)
     GetFullPathNameA(lpBuffer, dwSize, Dest, &pPtr);
 }
 
+inline bool IsSpecialFileName(const char* pName)
+{
+    /* specical file names are devices that the system can open
+     * these include AUX, CON, NUL, PRN, COMx, LPTx, CLOCK$, CONIN$, CONOUT$
+     * (x is a single digit, and names are case-insensitive)
+     */
+    char ch = (pName[0] & ~0x20);
+    switch (ch)
+    {
+	case 'A': /* AUX */
+	    if (((pName[1] & ~0x20) == 'U')
+		&& ((pName[2] & ~0x20) == 'X')
+		&& !pName[3])
+		    return true;
+	    break;
+	case 'C': /* CLOCK$, COMx,  CON, CONIN$ CONOUT$ */
+	    ch = (pName[1] & ~0x20);
+	    switch (ch)
+	    {
+		case 'L': /* CLOCK$ */
+		    if (((pName[2] & ~0x20) == 'O')
+			&& ((pName[3] & ~0x20) == 'C')
+			&& ((pName[4] & ~0x20) == 'K')
+			&& (pName[5] == '$')
+			&& !pName[6])
+			    return true;
+		    break;
+		case 'O': /* COMx,  CON, CONIN$ CONOUT$ */
+		    if ((pName[2] & ~0x20) == 'M') {
+			if ((pName[3] >= '1') && (pName[3] <= '9')
+			    && !pName[4])
+			    return true;
+		    }
+		    else if ((pName[2] & ~0x20) == 'N') {
+			if (!pName[3])
+			    return true;
+			else if ((pName[3] & ~0x20) == 'I') {
+			    if (((pName[4] & ~0x20) == 'N')
+				&& (pName[5] == '$')
+				&& !pName[6])
+			    return true;
+			}
+			else if ((pName[3] & ~0x20) == 'O') {
+			    if (((pName[4] & ~0x20) == 'U')
+				&& ((pName[5] & ~0x20) == 'T')
+				&& (pName[6] == '$')
+				&& !pName[7])
+			    return true;
+			}
+		    }
+		    break;
+	    }
+	    break;
+	case 'L': /* LPTx */
+	    if (((pName[1] & ~0x20) == 'U')
+		&& ((pName[2] & ~0x20) == 'X')
+		&& (pName[3] >= '1') && (pName[3] <= '9')
+		&& !pName[4])
+		    return true;
+	    break;
+	case 'N': /* NUL */
+	    if (((pName[1] & ~0x20) == 'U')
+		&& ((pName[2] & ~0x20) == 'L')
+		&& !pName[3])
+		    return true;
+	    break;
+	case 'P': /* PRN */
+	    if (((pName[1] & ~0x20) == 'R')
+		&& ((pName[2] & ~0x20) == 'N')
+		&& !pName[3])
+		    return true;
+	    break;
+    }
+    return false;
+}
+
 char *VDir::MapPathA(const char *pInName)
 {   /*
      * possiblities -- relative path or absolute path with or without drive letter
@@ -317,11 +411,16 @@ char *VDir::MapPathA(const char *pInName)
 	    }
 	    else {
 		/* relative path */
-		strcat(szBuffer, pInName);
-		if (strlen(szBuffer) > MAX_PATH)
-		    szBuffer[MAX_PATH] = '\0';
+		if (IsSpecialFileName(pInName)) {
+		    return (char*)pInName;
+		}
+		else {
+		    strcat(szBuffer, pInName);
+		    if (strlen(szBuffer) > MAX_PATH)
+			szBuffer[MAX_PATH] = '\0';
 
-		DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA);
+		    DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA);
+		}
 	    }
 	}
     }
@@ -408,6 +507,82 @@ inline void DoGetFullPathNameW(WCHAR* lpBuffer, DWORD dwSize, WCHAR* Dest)
     GetFullPathNameW(lpBuffer, dwSize, Dest, &pPtr);
 }
 
+inline bool IsSpecialFileName(const WCHAR* pName)
+{
+    /* specical file names are devices that the system can open
+     * these include AUX, CON, NUL, PRN, COMx, LPTx, CLOCK$, CONIN$, CONOUT$
+     * (x is a single digit, and names are case-insensitive)
+     */
+    WCHAR ch = (pName[0] & ~0x20);
+    switch (ch)
+    {
+	case 'A': /* AUX */
+	    if (((pName[1] & ~0x20) == 'U')
+		&& ((pName[2] & ~0x20) == 'X')
+		&& !pName[3])
+		    return true;
+	    break;
+	case 'C': /* CLOCK$, COMx,  CON, CONIN$ CONOUT$ */
+	    ch = (pName[1] & ~0x20);
+	    switch (ch)
+	    {
+		case 'L': /* CLOCK$ */
+		    if (((pName[2] & ~0x20) == 'O')
+			&& ((pName[3] & ~0x20) == 'C')
+			&& ((pName[4] & ~0x20) == 'K')
+			&& (pName[5] == '$')
+			&& !pName[6])
+			    return true;
+		    break;
+		case 'O': /* COMx,  CON, CONIN$ CONOUT$ */
+		    if ((pName[2] & ~0x20) == 'M') {
+			if ((pName[3] >= '1') && (pName[3] <= '9')
+			    && !pName[4])
+			    return true;
+		    }
+		    else if ((pName[2] & ~0x20) == 'N') {
+			if (!pName[3])
+			    return true;
+			else if ((pName[3] & ~0x20) == 'I') {
+			    if (((pName[4] & ~0x20) == 'N')
+				&& (pName[5] == '$')
+				&& !pName[6])
+			    return true;
+			}
+			else if ((pName[3] & ~0x20) == 'O') {
+			    if (((pName[4] & ~0x20) == 'U')
+				&& ((pName[5] & ~0x20) == 'T')
+				&& (pName[6] == '$')
+				&& !pName[7])
+			    return true;
+			}
+		    }
+		    break;
+	    }
+	    break;
+	case 'L': /* LPTx */
+	    if (((pName[1] & ~0x20) == 'U')
+		&& ((pName[2] & ~0x20) == 'X')
+		&& (pName[3] >= '1') && (pName[3] <= '9')
+		&& !pName[4])
+		    return true;
+	    break;
+	case 'N': /* NUL */
+	    if (((pName[1] & ~0x20) == 'U')
+		&& ((pName[2] & ~0x20) == 'L')
+		&& !pName[3])
+		    return true;
+	    break;
+	case 'P': /* PRN */
+	    if (((pName[1] & ~0x20) == 'R')
+		&& ((pName[2] & ~0x20) == 'N')
+		&& !pName[3])
+		    return true;
+	    break;
+    }
+    return false;
+}
+
 WCHAR* VDir::MapPathW(const WCHAR *pInName)
 {   /*
      * possiblities -- relative path or absolute path with or without drive letter
@@ -460,11 +635,16 @@ WCHAR* VDir::MapPathW(const WCHAR *pInName)
 	    }
 	    else {
 		/* relative path */
-		wcscat(szBuffer, pInName);
-		if (wcslen(szBuffer) > MAX_PATH)
-		    szBuffer[MAX_PATH] = '\0';
+		if (IsSpecialFileName(pInName)) {
+		    return (WCHAR*)pInName;
+		}
+		else {
+		    wcscat(szBuffer, pInName);
+		    if (wcslen(szBuffer) > MAX_PATH)
+			szBuffer[MAX_PATH] = '\0';
 
-		DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW);
+		    DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW);
+		}
 	    }
 	}
     }