X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=win32%2Fvdir.h;h=df9a10b13011f46bfdcf8047c7040075b5a4e27b;hb=1c94caf4a2d926d09d8fc04aa926eefd20ba5ed7;hp=0d21616df182c6cc54eec6b1a5d5049bbc8f583e;hpb=1d7c184104c076988718a01b77c8706aae05b092;p=p5sagit%2Fp5-mst-13.2.git diff --git a/win32/vdir.h b/win32/vdir.h index 0d21616..df9a10b 100644 --- a/win32/vdir.h +++ b/win32/vdir.h @@ -15,7 +15,7 @@ const int driveCount = 30; class VDir { public: - VDir(); + VDir(int bManageDir = 1); ~VDir() {}; void Init(VDir* pDir, VMem *pMem); @@ -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) { @@ -91,7 +109,7 @@ protected: }; VMem *pMem; - int nDefault; + int nDefault, bManageDirectory; char *dirTableA[driveCount]; char szLocalBufferA[MAX_PATH+1]; WCHAR *dirTableW[driveCount]; @@ -99,9 +117,10 @@ protected: }; -VDir::VDir() +VDir::VDir(int bManageDir /* = 1 */) { nDefault = 0; + bManageDirectory = bManageDir; memset(dirTableA, 0, sizeof(dirTableA)); memset(dirTableW, 0, sizeof(dirTableW)); } @@ -110,6 +129,7 @@ void VDir::Init(VDir* pDir, VMem *p) { int index; DWORD driveBits; + int nSave; char szBuffer[MAX_PATH*driveCount]; pMem = p; @@ -120,6 +140,8 @@ void VDir::Init(VDir* pDir, VMem *p) nDefault = pDir->GetDefault(); } else { + nSave = bManageDirectory; + bManageDirectory = 0; driveBits = GetLogicalDrives(); if (GetLogicalDriveStrings(sizeof(szBuffer), szBuffer)) { char* pEnv = GetEnvironmentStrings(); @@ -133,6 +155,7 @@ void VDir::Init(VDir* pDir, VMem *p) FreeEnvironmentStrings(pEnv); } SetDefaultA("."); + bManageDirectory = nSave; } } @@ -163,6 +186,10 @@ int VDir::SetDirA(char const *pPath, int index) } } } + + if(bManageDirectory) + ::SetCurrentDirectoryA(pPath); + return length; } @@ -217,6 +244,10 @@ int VDir::SetDirW(WCHAR const *pPath, int index) } } } + + if(bManageDirectory) + ::SetCurrentDirectoryW(pPath); + return length; } @@ -252,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 @@ -304,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); + } } } } @@ -321,32 +433,27 @@ int VDir::SetCurrentDirectoryA(char *lpBuffer) HANDLE hHandle; WIN32_FIND_DATA win32FD; char szBuffer[MAX_PATH+1], *pPtr; - int nRet = -1; + int length, nRet = -1; GetFullPathNameA(MapPathA(lpBuffer), sizeof(szBuffer), szBuffer, &pPtr); + /* if the last char is a '\\' or a '/' then add + * an '*' before calling FindFirstFile + */ + length = strlen(szBuffer); + if(length > 0 && IsPathSep(szBuffer[length-1])) { + szBuffer[length] = '*'; + szBuffer[length+1] = '\0'; + } - hHandle = FindFirstFile(szBuffer, &win32FD); + hHandle = FindFirstFileA(szBuffer, &win32FD); if (hHandle != INVALID_HANDLE_VALUE) { FindClose(hHandle); - SetDefaultDirA(szBuffer, DriveIndex(szBuffer[0])); - nRet = 0; - } - return nRet; -} -int VDir::SetCurrentDirectoryW(WCHAR *lpBuffer) -{ - HANDLE hHandle; - WIN32_FIND_DATAW win32FD; - WCHAR szBuffer[MAX_PATH+1], *pPtr; - int nRet = -1; - - GetFullPathNameW(MapPathW(lpBuffer), (sizeof(szBuffer)/sizeof(WCHAR)), szBuffer, &pPtr); + /* if an '*' was added remove it */ + if(szBuffer[length] == '*') + szBuffer[length] = '\0'; - hHandle = FindFirstFileW(szBuffer, &win32FD); - if (hHandle != INVALID_HANDLE_VALUE) { - FindClose(hHandle); - SetDefaultDirW(szBuffer, DriveIndex((char)szBuffer[0])); + SetDefaultDirA(szBuffer, DriveIndex(szBuffer[0])); nRet = 0; } return nRet; @@ -400,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 @@ -452,16 +635,51 @@ 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); + } } } } return szLocalBufferW; } +int VDir::SetCurrentDirectoryW(WCHAR *lpBuffer) +{ + HANDLE hHandle; + WIN32_FIND_DATAW win32FD; + WCHAR szBuffer[MAX_PATH+1], *pPtr; + int length, nRet = -1; + + GetFullPathNameW(MapPathW(lpBuffer), (sizeof(szBuffer)/sizeof(WCHAR)), szBuffer, &pPtr); + /* if the last char is a '\\' or a '/' then add + * an '*' before calling FindFirstFile + */ + length = wcslen(szBuffer); + if(length > 0 && IsPathSep(szBuffer[length-1])) { + szBuffer[length] = '*'; + szBuffer[length+1] = '\0'; + } + + hHandle = FindFirstFileW(szBuffer, &win32FD); + if (hHandle != INVALID_HANDLE_VALUE) { + FindClose(hHandle); + + /* if an '*' was added remove it */ + if(szBuffer[length] == '*') + szBuffer[length] = '\0'; + + SetDefaultDirW(szBuffer, DriveIndex((char)szBuffer[0])); + nRet = 0; + } + return nRet; +} #endif /* ___VDir_H___ */