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