/* truename.c -- truename Copyright (C) 1999-2000 Wojciech Galazka This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "lfnsrv.h" #include // thin toupper & isalpha to avoid msvcrt.dll char ttoupper(char c) { return ((c >= 'a' && c <= 'z')?(c-'a'+'A'):c); } char tisalpha(char c) { return (((c >='a' && c <= 'z') || (c >='A' && c <= 'Z'))?1:0); } WORD ValidDriveName( IN LPCSTR lpName, IN BYTE bFullCheck) { WORD result; IS_NULL(lpName, ERROR_PATH_NOT_FOUND); DBGVALUE(lpName,"%s"); DBGVALUE(bFullCheck,"%d"); if( lstrlen(lpName)==3 && lpName[1] == ':' && (lpName[2] == '\\' || lpName[2] == '/')) { WORD nDrive; DWORD dwDriveNum; DWORD dwPresentDrives; if (!tisalpha(lpName[0])) return ERROR_PATH_NOT_FOUND; nDrive = ttoupper(lpName[0])-'A'; //A=0,B=1.C=2,D=3,E=4 #if 0 dwDriveNum = (nDrive > 0)?(2 << (nDrive-1)):1; #else if (nDrive == 0) dwDriveNum = 1; else if (nDrive == 1) dwDriveNum = 2; else dwDriveNum = (2 << (nDrive-1)); #endif if (!(dwPresentDrives = GetLogicalDrives())) return (WORD)GetLastError(); DBGVALUE(dwPresentDrives,"%ld"); if (!(dwPresentDrives & dwDriveNum)) return ERROR_PATH_NOT_FOUND; // must return 0x3 if (bFullCheck) { char lpOrgPath[MAX_PATHNAME_SIZE]; if (!GetCurrentDirectory(MAX_PATHNAME_SIZE ,lpOrgPath)) { result = (WORD)GetLastError(); DBGMSG("GetCurDir call failed 1"); return result; } if (!SetCurrentDirectory(lpName)) { result = (WORD)GetLastError(); DBGMSG("SetCurDir call failed 2"); DBGVALUE(lpName,"%s"); DBGVALUE(result,"%d"); return ERROR_PATH_NOT_FOUND; } if (!SetCurrentDirectory(lpOrgPath)) { result = (WORD)GetLastError(); DBGMSG("GetCurDir call failed 3"); DBGVALUE(lpOrgPath,"%s"); return result; } } return ERROR_SUCCESS; } return ERROR_INVALID_DATA; } WORD GetLongPathName_( IN LPCSTR lpFileName, OUT LPSTR lpLongName) { BYTE nSize; BOOL bSlash = FALSE; HANDLE handle; WIN32_FIND_DATA FindStruct; char lpszOrgPath[MAX_PATHNAME_SIZE]; char lpszPath[MAX_PATHNAME_SIZE]; const char *b = &lpFileName[0]; char *s = &lpszOrgPath[0]; PROLOG(GetLongPathName_); IS_NULL(lpFileName, ERROR_PATH_NOT_FOUND); IS_NULL(lpLongName, ERROR_PATH_NOT_FOUND); DBGVALUE(lpFileName,"%s"); nSize = lstrlen(lpFileName); if (lpFileName[nSize-1] == '\\') bSlash = TRUE; *s++ = *(char *)b++; // x:/ drive *s++ = *(char *)b++; *s++ = *(char *)b++; *s = '\0'; lstrcpy(lpszPath,lpszOrgPath); while (*b) { while(*b && *b != '\\' && *b !='/') *s++ = *(char *)b++; *s = '\0'; memset(&FindStruct, 0, sizeof (WIN32_FIND_DATA)); if ((handle = FindFirstFile(lpszOrgPath, &FindStruct)) == INVALID_HANDLE_VALUE) { WORD result = (WORD)GetLastError(); DBGMSG("Failed to findfirst"); if (result == ERROR_NO_MORE_FILES || result == ERROR_PATH_NOT_FOUND || result == ERROR_FILE_NOT_FOUND) EPILOG(GetLongPathName_, TRUE); else EPILOG(GetLongPathName_, FALSE); if (result == ERROR_NO_MORE_FILES) result = ERROR_FILE_NOT_FOUND; return result; } lstrcat(lpszPath, FindStruct.cFileName); FindClose(handle); if (*b) { lstrcat(lpszPath, (*b == '\\')?"\\":"/"); *s++ = *(char *)b++; } } lstrcpy(lpLongName,lpszPath); if (bSlash == TRUE) { nSize = lstrlen(lpLongName); if (lpLongName[nSize-1] !='\\') { lpLongName[nSize] = '\\'; lpLongName[nSize+1] = '\0'; } } DBGVALUE(lpLongName, "%s"); EPILOG(GetLongPathName_, TRUE); return ERROR_SUCCESS; } WORD GetShortPathName_( IN LPCSTR lpFileName, OUT LPSTR lpShortName) { BYTE nSize; BOOL bSlash = FALSE; HANDLE handle; WIN32_FIND_DATA FindStruct; char lpszOrgPath[MAX_PATHNAME_SIZE]; char lpszPath[MAX_PATHNAME_SIZE]; const char *b = &lpFileName[0]; char *s = &lpszOrgPath[0]; PROLOG(GetShortPathName_); IS_NULL(lpFileName, ERROR_PATH_NOT_FOUND); IS_NULL(lpShortName, ERROR_PATH_NOT_FOUND); DBGVALUE(lpFileName,"%s"); nSize = lstrlen(lpFileName); if (lpFileName[nSize-1] == '\\') bSlash = TRUE; if ((lpFileName[1] ==':') && (lpFileName[2] == '/' || lpFileName[2] == '\\')) { *s++ = *(char *)b++; // x:/ drive *s++ = *(char *)b++; *s++ = *(char *)b++; } *s = '\0'; lstrcpy(lpszPath,lpszOrgPath); while (*b) { while(*b && *b != '\\' && *b !='/') *s++ = *(char *)b++; *s = '\0'; memset(&FindStruct, 0, sizeof (WIN32_FIND_DATA)); if ((handle = FindFirstFile(lpszOrgPath, &FindStruct)) == INVALID_HANDLE_VALUE) { WORD result = (WORD)GetLastError(); DBGMSG("Failed to findfirst"); if (result == ERROR_NO_MORE_FILES || result == ERROR_PATH_NOT_FOUND || result == ERROR_FILE_NOT_FOUND) EPILOG(GetShortPathName_, TRUE); else EPILOG(GetShortPathName_, FALSE); if (result == ERROR_NO_MORE_FILES) result = ERROR_FILE_NOT_FOUND; return result; } if (*(FindStruct.cAlternateFileName)) lstrcat(lpszPath, FindStruct.cAlternateFileName); else lstrcat(lpszPath, FindStruct.cFileName); FindClose(handle); if (*b) { lstrcat(lpszPath, (*b == '\\')?"\\":"/"); *s++ = *(char *)b++; } } lstrcpy(lpShortName,lpszPath); if (bSlash == TRUE) { nSize = lstrlen(lpShortName); if (lpShortName[nSize-1] !='\\') { lpShortName[nSize] = '\\'; lpShortName[nSize+1] = '\0'; } } DBGVALUE(lpShortName, "%s"); EPILOG(GetShortPathName_, TRUE); return ERROR_SUCCESS; } WORD process_truename( IN LPCSTR lpOldFileName, OUT LPSTR lpOrgNewFileName, IN BYTE nAction, IN BYTE nSubst) { WORD result ; char lpSavedFileName[MAX_PATHNAME_SIZE]; char * lpNewFileName; char lpNewFileName2[MAX_PATHNAME_SIZE]; char lpSubstName[MAX_PATHNAME_SIZE]; PROLOG(process_truename); DBGVALUE(nAction,"%d"); DBGVALUE(nSubst,"%d"); if (nSubst != LONG_TRUENAME_NO_SUBST && nSubst != LONG_TRUENAME_SUBST) { EPILOG(process_truename,TRUE); return ERROR_INVALID_FUNCTION; } if (nAction != LONG_TRUENAME_CLASS_CANONICAL && nAction != LONG_TRUENAME_CLASS_LONG && nAction != LONG_TRUENAME_CLASS_SHORT) { EPILOG(process_truename,TRUE); return ERROR_INVALID_FUNCTION; } IS_NULL(lpOldFileName, ERROR_PATH_NOT_FOUND); IS_MAX_PATH_SIZE(lpOldFileName); DBGVALUE(lpOldFileName,"%s"); if (lpOldFileName[0] == '\\' && lpOldFileName[1] == ':' ) { EPILOG(process_truename,TRUE); return ERROR_PATH_NOT_FOUND; // must return 0x3 } if (!lpOrgNewFileName) lpNewFileName = &lpNewFileName2[0]; else lpNewFileName = lpOrgNewFileName; lstrcpy(lpSavedFileName,lpOldFileName); *lpNewFileName = '\0'; if (!GetFullPathName(lpSavedFileName, MAX_PATHNAME_SIZE, lpNewFileName, NULL)) { result = (WORD)GetLastError(); DBGMSG("Failed to get absolute pathname"); DBGVALUE(result,"%d"); if (result != 0) { EPILOG(process_truename,FALSE); return result; } else lstrcpy(lpNewFileName,lpSavedFileName); } lpNewFileName[0] = ttoupper(lpNewFileName[0]); DBGVALUE(lpNewFileName,"%s"); if (nSubst == LONG_TRUENAME_NO_SUBST) { char lpszCurDir[]= "C:"; lpszCurDir[0]=lpNewFileName[0]; DBGVALUE(lpszCurDir,"%s"); if (!QueryDosDevice(lpszCurDir, lpSubstName, MAX_PATHNAME_SIZE)) { result = (WORD)GetLastError(); EPILOG(process_truename,TRUE); return result; } DBGVALUE(lpSubstName,"%s"); // // for substed drives the name is of type \??\X: // for persistent drives the name is of type \Device\Harddisk0\Partition1\ // if (lpSubstName[0] == '\\' && lpSubstName[1] == '?' && lpSubstName[2] == '?' && lpSubstName[3] == '\\') { BYTE nSize = lstrlen(lpSubstName); if (nSize-4+lstrlen(lpNewFileName) > MAX_PATHNAME_SIZE) { EPILOG(process_truename,TRUE); return ERROR_PATH_NOT_FOUND; } if (lpSubstName[nSize-1] !='\\') { lpSubstName[nSize] = '\\'; lpSubstName[nSize+1] = '\0'; } DBGVALUE(lpSubstName ,"%s"); lstrcpy(lpSubstName, lpSubstName+4); lstrcat(lpSubstName, lpNewFileName+3); lstrcpy(lpNewFileName, lpSubstName); DBGVALUE(lpNewFileName,"%s"); } } result = ValidDriveName(lpNewFileName, TRUE); if (result == ERROR_SUCCESS) { DBGVALUE(lpNewFileName,"%s"); EPILOG(process_truename,TRUE); return ERROR_SUCCESS; } if (result == ERROR_PATH_NOT_FOUND) { DBGVALUE(lpNewFileName,"%s"); *lpNewFileName = '\0'; EPILOG(process_truename,TRUE); return result; } if (nAction == LONG_TRUENAME_CLASS_CANONICAL) { DBGVALUE(lpNewFileName,"%s"); EPILOG(process_truename,TRUE); return ERROR_SUCCESS; } if (result != ERROR_INVALID_DATA) { DBGVALUE(lpNewFileName,"%s"); DBGMSG("Unexpected case"); *lpNewFileName = '\0'; EPILOG(process_truename,FALSE); return result ; } result = ERROR_SUCCESS; switch (nAction) { default: case LONG_TRUENAME_CLASS_CANONICAL: /*not reached*/ break; case LONG_TRUENAME_CLASS_SHORT: if ((result = FileExists(lpNewFileName)) != ERROR_SUCCESS) break; if(!GetShortPathName(lpNewFileName, lpNewFileName, MAX_PATHNAME_SIZE)) { result = (WORD)GetLastError(); DBGMSG("Cannot generate short filename 1"); if (result == ERROR_NOT_SUPPORTED) // The network request is not supported. if ((result = GetShortPathName_(lpNewFileName, lpNewFileName))) DBGMSG("Cannot generate short filename 2"); } break; case LONG_TRUENAME_CLASS_LONG: if ((result = GetLongPathName_(lpNewFileName, lpNewFileName))) DBGMSG("Cannot generate long filename"); break; } DBGVALUE(lpNewFileName,"%s"); if (result != ERROR_SUCCESS) { *lpNewFileName = '\0'; if (result == ERROR_PATH_NOT_FOUND || result == ERROR_FILE_NOT_FOUND) EPILOG(process_truename,TRUE); else EPILOG(process_truename,FALSE); return result; } EPILOG(process_truename,TRUE); return ERROR_SUCCESS; } WORD FileExists( IN LPCSTR lpName) { HANDLE handle; WIN32_FIND_DATA FindStruct; WORD result; char lpSavedName[MAX_PATHNAME_SIZE]; BYTE nSize; PROLOG(FileExists); ISNULL(lpName); DBGVALUE(lpName,"%s"); memset(&FindStruct, 0, sizeof (WIN32_FIND_DATA)); lstrcpy(lpSavedName, lpName); nSize = lstrlen(lpSavedName); if (lpSavedName[nSize-1] == '\\' || lpSavedName[nSize-1] == '/') lpSavedName[nSize-1] = '\0'; if ((handle = FindFirstFile(lpSavedName, &FindStruct)) != INVALID_HANDLE_VALUE) { FindClose(handle); result = ERROR_SUCCESS; } else result = (WORD)GetLastError(); DBGVALUE(result,"%d"); EPILOG(FileExists, TRUE); return result; }