views:

343

answers:

2

I'm looking for a method to get corresponding local path for a given UNC path. Microsoft provides a small library CheckLCL for this purpose. This library is not supported on all Windows versions. Does anybody know any open source method for this?

There is also MAPI function ScLocalPathFromUNC, but am not sure if it works on all platforms.

A: 

The System.Uri class may be some help.

http://msdn.microsoft.com/en-us/library/system.uri.aspx

It is similar to UNC and has a IsUNC() method.

Soppus
Thanks for the hint! If you are interested, i have the solution now.
mem64k
A: 

After some googling and digging in MSDN i have the following solution:

#include <Crtdbg.h>    // for debug stuff
#include "Winnetwk.h"  // for WNetGetUniversalName()
#include "Lm.h"        // for NetShareGetInfo()
#include "pystring.h"  // from http://code.google.com/p/pystring

#pragma comment( lib, "Mpr.lib" )       // for WNetGetUniversalName()
#pragma comment( lib, "Netapi32.lib" )  // for NetShareGetInfo()

//-----------------------------------------------------------------------------
// converts x:\\folder -> \\\\server\\share\\folder
bool ConvertLocalPathToUNC(const char* szFilePath, std::string& strUNC)
{
  // get size of the remote name buffer
  DWORD dwBufferSize = 0;
  char szBuff[2];
  if (::WNetGetUniversalName(szFilePath, UNIVERSAL_NAME_INFO_LEVEL, szBuff, &dwBufferSize) == ERROR_MORE_DATA)
  {
    // get remote name of the share
    char* buf = new char[dwBufferSize];
    UNIVERSAL_NAME_INFO* puni = (UNIVERSAL_NAME_INFO*) buf;

    if (::WNetGetUniversalName(szFilePath, UNIVERSAL_NAME_INFO_LEVEL, buf, &dwBufferSize) == NO_ERROR)
    {
      strUNC = puni->lpUniversalName;
      delete [] buf;
      return true;
    }
    delete [] buf;
  }

  return false;
}

//-----------------------------------------------------------------------------
// converts \\\\server\\share\\folder -> x:\\folder
bool ConvertUNCToLocalPath(const char* szUNC, std::string& strLocalPath)
{
  // get share name from UNC
  std::string strUNC(szUNC);
  std::vector< std::string > vecTokens;
  pystring::split(strUNC, vecTokens, _T("\\"));

  if (vecTokens.size() < 4)
    return false;

  // we need wchar for NetShareGetInfo()
  std::wstring strShare(vecTokens[3].length(), L' ');
  std::copy(vecTokens[3].begin(), vecTokens[3].end(), strShare.begin());

  PSHARE_INFO_502  BufPtr;
  NET_API_STATUS   res;
  if ((res = NetShareGetInfo(NULL, const_cast<LPWSTR>(strShare.c_str()), 502, (LPBYTE*) &BufPtr)) == ERROR_SUCCESS)
  {
    // print the retrieved data.
    _RPTF3(_CRT_WARN, _T("%ls\t%ls\t%u\n"), BufPtr->shi502_netname, BufPtr->shi502_path, BufPtr->shi502_current_uses);

    std::wstring strPath(BufPtr->shi502_path);
    strLocalPath.assign(strPath.begin(), strPath.end());

    // build local path
    for (size_t i = 4; i < vecTokens.size(); ++i)
    {
      if (!pystring::endswith(strLocalPath, _T("\\")))
        strLocalPath += _T("\\");
      strLocalPath += vecTokens[i];
    }

    // Validate the value of the shi502_security_descriptor member.
    if (IsValidSecurityDescriptor(BufPtr->shi502_security_descriptor))
      _RPTF0(_CRT_WARN, _T("It has a valid Security Descriptor.\n"));
    else
      _RPTF0(_CRT_WARN, _T("It does not have a valid Security Descriptor.\n"));

    // Free the allocated memory.
    NetApiBufferFree(BufPtr);
  }
  else
    return false;

  return true;
}
mem64k