Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
#define UNICODE // per le funzioni di conversione da/a UNC
Toshihiro Shimizu 890ddd
#include <windows.h></windows.h>
Toshihiro Shimizu 890ddd
#include <lm.h></lm.h>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSystem::isUNC(const TFilePath &path)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// si assume che il path e' gia' in formato UNC se inizia con "\\"
Shinya Kitaoka 3bfa54
	std::wstring pathStr = path.getWideString();
Toshihiro Shimizu 890ddd
	return pathStr.length() > 2 && pathStr.substr(0, 2) == L"\\\\";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFilePath TSystem::toUNC(const TFilePath &fp)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
	if (QString::fromStdWString(fp.getWideString()).startsWith('+'))
Toshihiro Shimizu 890ddd
		return fp;
Toshihiro Shimizu 890ddd
	if (isUNC(fp))
Toshihiro Shimizu 890ddd
		return fp;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9eb50d
	std::string fpStr = ::to_string(fp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (fpStr.length() > 1 && fpStr.c_str()[1] == ':') {
Shinya Kitaoka 3bfa54
		std::string drive = fpStr.substr(0, 3);
Toshihiro Shimizu 890ddd
		UINT uiDriveType = GetDriveTypeA(drive.c_str());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (uiDriveType & DRIVE_REMOTE) {
Toshihiro Shimizu 890ddd
			// il drive e' montato
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			DWORD cbBuff = _MAX_PATH; // Size of buffer
Toshihiro Shimizu 890ddd
			char szBuff[_MAX_PATH];   // Buffer to receive information
Toshihiro Shimizu 890ddd
			REMOTE_NAME_INFO *prni = (REMOTE_NAME_INFO *)&szBuff;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Pointers to head of buffer
Toshihiro Shimizu 890ddd
			UNIVERSAL_NAME_INFO *puni = (UNIVERSAL_NAME_INFO *)&szBuff;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9eb50d
			DWORD dwResult = WNetGetUniversalNameW(::to_wstring(fpStr).c_str(),
Toshihiro Shimizu 890ddd
												   UNIVERSAL_NAME_INFO_LEVEL,
Toshihiro Shimizu 890ddd
												   (LPVOID)&szBuff,
Toshihiro Shimizu 890ddd
												   &cbBuff);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			switch (dwResult) {
Toshihiro Shimizu 890ddd
			case NO_ERROR:
Shinya Kitaoka 9eb50d
				return TFilePath(::to_string(puni->lpUniversalName));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			case ERROR_NOT_CONNECTED:
Toshihiro Shimizu 890ddd
				// The network connection does not exists.
Toshihiro Shimizu 890ddd
				throw TException("The path specified doesn't refer to a shared folder");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			case ERROR_CONNECTION_UNAVAIL:
Toshihiro Shimizu 890ddd
				// The device is not currently connected,
Toshihiro Shimizu 890ddd
				// but it is a persistent connection.
Toshihiro Shimizu 890ddd
				throw TException("The shared folder is not currently connected");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			default:
Toshihiro Shimizu 890ddd
				throw TException("Cannot convert the path specified to UNC");
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			//  It's a local drive so search for a share to it...
Toshihiro Shimizu 890ddd
			NET_API_STATUS res;
Toshihiro Shimizu 890ddd
			PSHARE_INFO_502 BufPtr, p;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			DWORD er = 0,
Toshihiro Shimizu 890ddd
				  tr = 0,
Toshihiro Shimizu 890ddd
				  resume = 0,
Toshihiro Shimizu 890ddd
				  i;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			int iBestMatch = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
			std::string csTemp,
Toshihiro Shimizu 890ddd
				csTempDrive,
Toshihiro Shimizu 890ddd
				csBestMatch;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			do {
Toshihiro Shimizu 890ddd
				res = NetShareEnum(NULL, 502, (LPBYTE *)&BufPtr, MAX_PREFERRED_LENGTH, &er, &tr, &resume);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// If the call succeeds,
Toshihiro Shimizu 890ddd
				if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) {
Toshihiro Shimizu 890ddd
					p = BufPtr;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					// Loop through the entries;
Toshihiro Shimizu 890ddd
					for (i = 1; i <= er; i++) {
Toshihiro Shimizu 890ddd
						if (p->shi502_type == STYPE_DISKTREE) {
Toshihiro Shimizu 890ddd
							//#ifdef IS_DOTNET
Toshihiro Shimizu 890ddd
							// shi502_path e' una wstring, aanche se la dichiarazione di PSHARE_INFO_502 non lo sa!
Shinya Kitaoka 3bfa54
							std::wstring shareLocalPathW = (LPWSTR)(p->shi502_path);
Shinya Kitaoka 9eb50d
							std::string shareLocalPath = ::to_string(shareLocalPathW);
Toshihiro Shimizu 890ddd
							//#else
Toshihiro Shimizu 890ddd
							//string shareLocalPath = toString(p->shi502_path);
Toshihiro Shimizu 890ddd
							//#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							if (toLower(fpStr).find(toLower(shareLocalPath)) == 0) {
Shinya Kitaoka 3bfa54
								std::string hostName = TSystem::getHostName().toStdString();
Toshihiro Shimizu 890ddd
								//   #ifdef IS_DOTNET
Toshihiro Shimizu 890ddd
								// shi502_netname e' una wstring, anche se la dichiarazione di PSHARE_INFO_502 non lo sa!
Shinya Kitaoka 3bfa54
								std::wstring shareNetNameW = (LPWSTR)(p->shi502_netname);
Shinya Kitaoka 9eb50d
								std::string shareNetName = ::to_string(shareNetNameW);
Toshihiro Shimizu 890ddd
								//	 #else
Toshihiro Shimizu 890ddd
								//string shareNetName = toString(p->shi502_netname);
Toshihiro Shimizu 890ddd
								//#endif
Toshihiro Shimizu 890ddd
								shareNetName.append("\\");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
								std::string fp(fpStr);
Shinya Kitaoka 3bfa54
								std::string uncpath = "\\\\" + hostName + "\\" +
Toshihiro Shimizu 890ddd
												 fp.replace(0, shareLocalPath.size(), shareNetName);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
								return TFilePath(uncpath);
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						p++;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					// Free the allocated buffer.
Toshihiro Shimizu 890ddd
					NetApiBufferFree(BufPtr);
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					//TRACE(_T("Error: %ld\n"), res);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// Continue to call NetShareEnum while
Toshihiro Shimizu 890ddd
				//  there are more entries.
Toshihiro Shimizu 890ddd
				//
Toshihiro Shimizu 890ddd
			} while (res == ERROR_MORE_DATA); // end do
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//throw TException("Cannot convert the path specified to UNC");
Toshihiro Shimizu 890ddd
	return fp;
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	//throw TException("Cannot convert the path specified to UNC");
Toshihiro Shimizu 890ddd
	return fp;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFilePath TSystem::toLocalPath(const TFilePath &fp)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
	if (!isUNC(fp))
Toshihiro Shimizu 890ddd
		return TFilePath(fp);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9eb50d
	std::string pathStr = ::to_string(fp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// estrae hostname e il nome dello share dal path UNC
Shinya Kitaoka 3bfa54
	std::string::size_type idx = pathStr.find_first_of("\\", 2);
Shinya Kitaoka 3bfa54
	if (idx == std::string::npos)
Toshihiro Shimizu 890ddd
		throw TException("The path specified is not a valid UNC path");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::string hostname = pathStr.substr(2, idx - 2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (toLower(hostname) != toLower(TSystem::getHostName().toStdString()))
Toshihiro Shimizu 890ddd
		throw TException("The UNC path specified does not refer to the local host");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::string::size_type idx2 = pathStr.find_first_of("\\", idx + 1);
Shinya Kitaoka 3bfa54
	if (idx2 == std::string::npos)
Toshihiro Shimizu 890ddd
		throw TException("The path specified is not a valid UNC path");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::string fpShareName = pathStr.substr(idx + 1, idx2 - idx - 1);
Shinya Kitaoka 3bfa54
	std::string path = pathStr.substr(idx2 + 1, pathStr.size() - idx2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	NET_API_STATUS res;
Toshihiro Shimizu 890ddd
	do {
Toshihiro Shimizu 890ddd
		PSHARE_INFO_502 BufPtr, p;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		DWORD er = 0, tr = 0, resume = 0;
Toshihiro Shimizu 890ddd
		res = NetShareEnum(NULL, 502, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// If the call succeeds,
Toshihiro Shimizu 890ddd
		if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) {
Toshihiro Shimizu 890ddd
			p = BufPtr;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Loop through the entries;
Toshihiro Shimizu 890ddd
			for (int i = 1; i <= (int)er; i++) {
Toshihiro Shimizu 890ddd
				if (p->shi502_type == STYPE_DISKTREE) {
Toshihiro Shimizu 890ddd
					//#ifdef IS_DOTNET
Toshihiro Shimizu 890ddd
					//shi502_netname e' una wstring, anche se la dichiarazione di PSHARE_INFO_502 non lo sa!
Shinya Kitaoka 3bfa54
					std::wstring shareNetNameW = (LPWSTR)(p->shi502_netname);
Shinya Kitaoka 9eb50d
					std::string shareNetName = ::to_string(shareNetNameW);
Toshihiro Shimizu 890ddd
					//	#else
Toshihiro Shimizu 890ddd
					//string shareNetName = toString(p->shi502_netname);
Toshihiro Shimizu 890ddd
					//#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (toLower(fpShareName) == toLower(shareNetName)) {
Toshihiro Shimizu 890ddd
						//#ifdef IS_DOTNET
Toshihiro Shimizu 890ddd
						// shi502_path e' una wstring, anche se la dichiarazione di PSHARE_INFO_502 non lo sa!
Shinya Kitaoka 3bfa54
						std::wstring shareLocalPathW = (LPWSTR)(p->shi502_path);
Shinya Kitaoka 9eb50d
						std::string shareLocalPath = ::to_string(shareLocalPathW);
Toshihiro Shimizu 890ddd
						//#else
Toshihiro Shimizu 890ddd
						//string shareLocalPath = toString(p->shi502_path);
Toshihiro Shimizu 890ddd
						//#endif
Shinya Kitaoka 3bfa54
						std::string localPath = shareLocalPath + path;
Toshihiro Shimizu 890ddd
						return TFilePath(localPath);
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				p++;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Free the allocated buffer.
Toshihiro Shimizu 890ddd
			NetApiBufferFree(BufPtr);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			//TRACE(_T("Error: %ld\n"), res);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Continue to call NetShareEnum while
Toshihiro Shimizu 890ddd
		//  there are more entries.
Toshihiro Shimizu 890ddd
		//
Toshihiro Shimizu 890ddd
	} while (res == ERROR_MORE_DATA); // end do
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	throw TException("Cannot convert to a local path");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	throw TException("Cannot convert to a local path");
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}