| |
| |
| #include "tsystem.h" |
| #include "tconvert.h" |
| |
| #ifdef _WIN32 |
| #define UNICODE |
| #include <windows.h> |
| #include <lm.h> |
| #endif |
| |
| |
| |
| bool TSystem::isUNC(const TFilePath &path) { |
| |
| std::wstring pathStr = path.getWideString(); |
| return pathStr.length() > 2 && pathStr.substr(0, 2) == L"\\\\"; |
| } |
| |
| |
| |
| TFilePath TSystem::toUNC(const TFilePath &fp) { |
| #ifdef _WIN32 |
| if (QString::fromStdWString(fp.getWideString()).startsWith('+')) return fp; |
| if (isUNC(fp)) return fp; |
| |
| std::string fpStr = ::to_string(fp); |
| |
| if (fpStr.length() > 1 && fpStr.c_str()[1] == ':') { |
| std::string drive = fpStr.substr(0, 3); |
| UINT uiDriveType = GetDriveTypeA(drive.c_str()); |
| |
| if (uiDriveType & DRIVE_REMOTE) { |
| |
| |
| DWORD cbBuff = _MAX_PATH; |
| char szBuff[_MAX_PATH]; |
| REMOTE_NAME_INFO *prni = (REMOTE_NAME_INFO *)&szBuff; |
| |
| |
| UNIVERSAL_NAME_INFO *puni = (UNIVERSAL_NAME_INFO *)&szBuff; |
| |
| DWORD dwResult = WNetGetUniversalNameW(::to_wstring(fpStr).c_str(), |
| UNIVERSAL_NAME_INFO_LEVEL, |
| (LPVOID)&szBuff, &cbBuff); |
| |
| switch (dwResult) { |
| case NO_ERROR: |
| return TFilePath(::to_string(puni->lpUniversalName)); |
| |
| case ERROR_NOT_CONNECTED: |
| |
| throw TException("The path specified doesn't refer to a shared folder"); |
| |
| case ERROR_CONNECTION_UNAVAIL: |
| |
| |
| throw TException("The shared folder is not currently connected"); |
| |
| default: |
| throw TException("Cannot convert the path specified to UNC"); |
| } |
| } else { |
| |
| NET_API_STATUS res; |
| PSHARE_INFO_502 BufPtr, p; |
| |
| DWORD er = 0, tr = 0, resume = 0, i; |
| |
| int iBestMatch = 0; |
| |
| std::string csTemp, csTempDrive, csBestMatch; |
| |
| do { |
| res = NetShareEnum(NULL, 502, (LPBYTE *)&BufPtr, MAX_PREFERRED_LENGTH, |
| &er, &tr, &resume); |
| |
| |
| if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) { |
| p = BufPtr; |
| |
| |
| for (i = 1; i <= er; i++) { |
| if (p->shi502_type == STYPE_DISKTREE) { |
| |
| |
| |
| std::wstring shareLocalPathW = (LPWSTR)(p->shi502_path); |
| std::string shareLocalPath = ::to_string(shareLocalPathW); |
| |
| |
| |
| |
| if (toLower(fpStr).find(toLower(shareLocalPath)) == 0) { |
| std::string hostName = TSystem::getHostName().toStdString(); |
| |
| |
| |
| std::wstring shareNetNameW = (LPWSTR)(p->shi502_netname); |
| std::string shareNetName = ::to_string(shareNetNameW); |
| |
| |
| |
| shareNetName.append("\\"); |
| |
| std::string fp(fpStr); |
| std::string uncpath = |
| "\\\\" + hostName + "\\" + |
| fp.replace(0, shareLocalPath.size(), shareNetName); |
| |
| return TFilePath(uncpath); |
| } |
| } |
| |
| p++; |
| } |
| |
| |
| NetApiBufferFree(BufPtr); |
| } else { |
| |
| } |
| |
| |
| |
| |
| } while (res == ERROR_MORE_DATA); |
| } |
| } |
| |
| |
| return fp; |
| #else |
| |
| return fp; |
| #endif |
| } |
| |
| |
| |
| TFilePath TSystem::toLocalPath(const TFilePath &fp) { |
| #ifdef _WIN32 |
| if (!isUNC(fp)) return TFilePath(fp); |
| |
| std::string pathStr = ::to_string(fp); |
| |
| |
| std::string::size_type idx = pathStr.find_first_of("\\", 2); |
| if (idx == std::string::npos) |
| throw TException("The path specified is not a valid UNC path"); |
| |
| std::string hostname = pathStr.substr(2, idx - 2); |
| |
| if (toLower(hostname) != toLower(TSystem::getHostName().toStdString())) |
| throw TException("The UNC path specified does not refer to the local host"); |
| |
| std::string::size_type idx2 = pathStr.find_first_of("\\", idx + 1); |
| if (idx2 == std::string::npos) |
| throw TException("The path specified is not a valid UNC path"); |
| |
| std::string fpShareName = pathStr.substr(idx + 1, idx2 - idx - 1); |
| std::string path = pathStr.substr(idx2 + 1, pathStr.size() - idx2); |
| |
| NET_API_STATUS res; |
| do { |
| PSHARE_INFO_502 BufPtr, p; |
| |
| DWORD er = 0, tr = 0, resume = 0; |
| res = NetShareEnum(NULL, 502, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, |
| &resume); |
| |
| |
| if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) { |
| p = BufPtr; |
| |
| |
| for (int i = 1; i <= (int)er; i++) { |
| if (p->shi502_type == STYPE_DISKTREE) { |
| |
| |
| |
| std::wstring shareNetNameW = (LPWSTR)(p->shi502_netname); |
| std::string shareNetName = ::to_string(shareNetNameW); |
| |
| |
| |
| |
| if (toLower(fpShareName) == toLower(shareNetName)) { |
| |
| |
| |
| std::wstring shareLocalPathW = (LPWSTR)(p->shi502_path); |
| std::string shareLocalPath = ::to_string(shareLocalPathW); |
| |
| |
| |
| std::string localPath = shareLocalPath + path; |
| return TFilePath(localPath); |
| } |
| } |
| |
| p++; |
| } |
| |
| |
| NetApiBufferFree(BufPtr); |
| } else { |
| |
| } |
| |
| |
| |
| |
| } while (res == ERROR_MORE_DATA); |
| |
| throw TException("Cannot convert to a local path"); |
| |
| #else |
| throw TException("Cannot convert to a local path"); |
| #endif |
| } |
| |