示例#1
0
RTDECL(int) RTEnvGetUtf8(const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual)
{
    AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
    AssertPtrNullReturn(pszValue, VERR_INVALID_POINTER);
    AssertReturn(pszValue || !cbValue, VERR_INVALID_PARAMETER);
    AssertPtrNullReturn(pcchActual, VERR_INVALID_POINTER);
    AssertReturn(pcchActual || (pszValue && cbValue), VERR_INVALID_PARAMETER);
    AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME);

    if (pcchActual)
        *pcchActual = 0;

    PRTUTF16 pwszVar;
    int rc = RTStrToUtf16(pszVar, &pwszVar);
    AssertRCReturn(rc, rc);

    /** @todo Consider _wgetenv_s or GetEnvironmentVariableW here to avoid the
     *        potential race with a concurrent _wputenv/_putenv. */
    PCRTUTF16 pwszValue = _wgetenv(pwszVar);
    RTUtf16Free(pwszVar);
    if (pwszValue)
    {
        if (cbValue)
            rc = RTUtf16ToUtf8Ex(pwszValue, RTSTR_MAX, &pszValue, cbValue, pcchActual);
        else
            rc = RTUtf16CalcUtf8LenEx(pwszValue, RTSTR_MAX, pcchActual);
    }
    else
        rc = VERR_ENV_VAR_NOT_FOUND;
    return rc;
}
示例#2
0
RTDECL(int) RTPathUserDocuments(char *pszPath, size_t cchPath)
{
    /*
     * Validate input
     */
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(cchPath, VERR_INVALID_PARAMETER);

    RTLDRMOD hShell32;
    int rc = RTLdrLoad("Shell32.dll", &hShell32);
    if (RT_SUCCESS(rc))
    {
        PFNSHGETFOLDERPATHW pfnSHGetFolderPathW;
        rc = RTLdrGetSymbol(hShell32, "SHGetFolderPathW", (void**)&pfnSHGetFolderPathW);
        if (RT_SUCCESS(rc))
        {
            RTUTF16 wszPath[RTPATH_MAX];
            HRESULT hrc = pfnSHGetFolderPathW(0, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, wszPath);
            if (   hrc == S_OK     /* Found */
                || hrc == S_FALSE) /* Found, but doesn't exist */
            {
                /*
                 * Convert and return.
                 */
                RTLdrClose(hShell32);
                return RTUtf16ToUtf8Ex(&wszPath[0], RTSTR_MAX, &pszPath, cchPath, NULL);
            }
        }
        RTLdrClose(hShell32);
    }
    return VERR_PATH_NOT_FOUND;
}
int rtldrNativeLoadSystem(const char *pszFilename, const char *pszExt, uint32_t fFlags, PRTLDRMOD phLdrMod)
{
    /*
     * We only try the System32 directory.
     */
    WCHAR wszSysDir[MAX_PATH];
    UINT cwcSysDir = GetSystemDirectoryW(wszSysDir, MAX_PATH);
    if (cwcSysDir >= MAX_PATH)
        return VERR_FILENAME_TOO_LONG;

    char szPath[RTPATH_MAX];
    char *pszPath = szPath;
    int rc = RTUtf16ToUtf8Ex(wszSysDir, RTSTR_MAX, &pszPath, sizeof(szPath), NULL);
    if (RT_SUCCESS(rc))
    {
        rc = RTPathAppend(szPath, sizeof(szPath), pszFilename);
        if (pszExt && RT_SUCCESS(rc))
            rc = RTStrCat(szPath, sizeof(szPath), pszExt);
        if (RT_SUCCESS(rc))
        {
            if (RTFileExists(szPath))
                rc = RTLdrLoadEx(szPath, phLdrMod, fFlags, NULL);
            else
                rc = VERR_MODULE_NOT_FOUND;
        }
    }

    return rc;
}
示例#4
0
/**
 * Get the real (no symlinks, no . or .. components) path, must exist.
 *
 * @returns iprt status code.
 * @param   pszPath         The path to resolve.
 * @param   pszRealPath     Where to store the real path.
 * @param   cchRealPath     Size of the buffer.
 */
RTDECL(int) RTPathReal(const char *pszPath, char *pszRealPath, size_t cchRealPath)
{
    /*
     * Convert to UTF-16, call Win32 APIs, convert back.
     */
    PRTUTF16 pwszPath;
    int rc = RTStrToUtf16(pszPath, &pwszPath);
    if (!RT_SUCCESS(rc))
        return (rc);

    LPWSTR lpFile;
    WCHAR  wsz[RTPATH_MAX];
    rc = GetFullPathNameW((LPCWSTR)pwszPath, RT_ELEMENTS(wsz), &wsz[0], &lpFile);
    if (rc > 0 && rc < RT_ELEMENTS(wsz))
    {
        /* Check that it exists. (Use RTPathAbs() to just resolve the name.) */
        DWORD dwAttr = GetFileAttributesW(wsz);
        if (dwAttr != INVALID_FILE_ATTRIBUTES)
            rc = RTUtf16ToUtf8Ex((PRTUTF16)&wsz[0], RTSTR_MAX, &pszRealPath, cchRealPath, NULL);
        else
            rc = RTErrConvertFromWin32(GetLastError());
    }
    else if (rc <= 0)
        rc = RTErrConvertFromWin32(GetLastError());
    else
        rc = VERR_FILENAME_TOO_LONG;

    RTUtf16Free(pwszPath);

    return rc;
}
示例#5
0
VBOXUSBTOOL_DECL(NTSTATUS) VBoxUsbToolGetStringDescriptor(PDEVICE_OBJECT pDevObj, char *pszResult, ULONG cbResult,
                                                          int iIndex, int LangId, ULONG dwTimeoutMs)
{
    char aBuf[MAXIMUM_USB_STRING_LENGTH];
    AssertCompile(sizeof (aBuf) <= UINT8_MAX);
    UCHAR cbBuf = (UCHAR)sizeof (aBuf);
    PUSB_STRING_DESCRIPTOR pDr = (PUSB_STRING_DESCRIPTOR)&aBuf;

    Assert(pszResult);
    *pszResult = 0;

    memset(pDr, 0, cbBuf);
    pDr->bLength = cbBuf;
    pDr->bDescriptorType = USB_STRING_DESCRIPTOR_TYPE;

    NTSTATUS Status = VBoxUsbToolGetDescriptor(pDevObj, pDr, cbBuf, USB_STRING_DESCRIPTOR_TYPE, iIndex, LangId, dwTimeoutMs);
    if (NT_SUCCESS(Status))
    {
        if (pDr->bLength >= sizeof (USB_STRING_DESCRIPTOR))
        {
            int rc = RTUtf16ToUtf8Ex(pDr->bString, (pDr->bLength - RT_OFFSETOF(USB_STRING_DESCRIPTOR, bString)) / sizeof(RTUTF16),
                                     &pszResult, cbResult, NULL /*pcch*/);
            if (RT_SUCCESS(rc))
            {
                USBLibPurgeEncoding(pszResult);
                Status = STATUS_SUCCESS;
            }
            else
                Status = STATUS_UNSUCCESSFUL;
        }
        else
            Status = STATUS_INVALID_PARAMETER;
    }
    return Status;
}
示例#6
0
/**
 * Gets the user home directory.
 *
 * @returns iprt status code.
 * @param   pszPath     Buffer where to store the path.
 * @param   cchPath     Buffer size in bytes.
 */
RTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath)
{
    RTUTF16 wszPath[RTPATH_MAX];
    DWORD   dwAttr;

    /*
     * There are multiple definitions for what WE think of as user home...
     */
    if (    !GetEnvironmentVariableW(L"HOME", &wszPath[0], RTPATH_MAX)
        ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
        ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
    {
        if (    !GetEnvironmentVariableW(L"USERPROFILE", &wszPath[0], RTPATH_MAX)
            ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
            ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
        {
            /* %HOMEDRIVE%%HOMEPATH% */
            if (!GetEnvironmentVariableW(L"HOMEDRIVE", &wszPath[0], RTPATH_MAX))
                return VERR_PATH_NOT_FOUND;
            size_t const cwc = RTUtf16Len(&wszPath[0]);
            if (    !GetEnvironmentVariableW(L"HOMEPATH", &wszPath[cwc], RTPATH_MAX - (DWORD)cwc)
                ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
                ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
                return VERR_PATH_NOT_FOUND;
        }
    }

    /*
     * Convert and return.
     */
    return RTUtf16ToUtf8Ex(&wszPath[0], RTSTR_MAX, &pszPath, cchPath, NULL);
}
示例#7
0
/**
 * A variant of Utf8Str::copyFrom that does not throw any exceptions but returns
 * E_OUTOFMEMORY instead.
 *
 * @param   a_pbstr         The source string.
 * @returns S_OK or E_OUTOFMEMORY.
 */
HRESULT Utf8Str::copyFromEx(CBSTR a_pbstr)
{
    if (a_pbstr && *a_pbstr)
    {
        int vrc = RTUtf16ToUtf8Ex((PCRTUTF16)a_pbstr,
                                  RTSTR_MAX,        // size_t cwcString: translate entire string
                                  &m_psz,           // char **ppsz: output buffer
                                  0,                // size_t cch: if 0, func allocates buffer in *ppsz
                                  &m_cch);          // size_t *pcch: receives the size of the output string, excluding the terminator.
        if (RT_SUCCESS(vrc))
            m_cbAllocated = m_cch + 1;
        else
        {
            if (   vrc != VERR_NO_STR_MEMORY
                && vrc != VERR_NO_MEMORY)
            {
                /* ASSUME: input is valid Utf-16. Fake out of memory error. */
                AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTUtf16Len((PCRTUTF16)a_pbstr) * sizeof(RTUTF16), a_pbstr));
            }

            m_cch = 0;
            m_cbAllocated = 0;
            m_psz = NULL;

            return E_OUTOFMEMORY;
        }
    }
    else
    {
        m_cch = 0;
        m_cbAllocated = 0;
        m_psz = NULL;
    }
    return S_OK;
}
/**
 * Gets the user home directory.
 *
 * @returns iprt status code.
 * @param   pszPath     Buffer where to store the path.
 * @param   cchPath     Buffer size in bytes.
 */
RTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath)
{
    /*
     * Validate input
     */
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(cchPath, VERR_INVALID_PARAMETER);

    RTUTF16 wszPath[RTPATH_MAX];
    bool    fValidFolderPath = false;

    /*
     * Try with Windows XP+ functionality first.
     */
    RTLDRMOD hShell32;
    int rc = RTLdrLoadSystem("Shell32.dll", true /*fNoUnload*/, &hShell32);
    if (RT_SUCCESS(rc))
    {
        PFNSHGETFOLDERPATHW pfnSHGetFolderPathW;
        rc = RTLdrGetSymbol(hShell32, "SHGetFolderPathW", (void**)&pfnSHGetFolderPathW);
        if (RT_SUCCESS(rc))
        {
            HRESULT hrc = pfnSHGetFolderPathW(0, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, wszPath);
            fValidFolderPath = (hrc == S_OK);
        }
        RTLdrClose(hShell32);
    }

    DWORD   dwAttr;
    if (    !fValidFolderPath
        ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
        ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
    {
        /*
         * Fall back to Windows specific environment variables. HOME is not used.
         */
        if (    !GetEnvironmentVariableW(L"USERPROFILE", &wszPath[0], RTPATH_MAX)
            ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
            ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
        {
            /* %HOMEDRIVE%%HOMEPATH% */
            if (!GetEnvironmentVariableW(L"HOMEDRIVE", &wszPath[0], RTPATH_MAX))
                return VERR_PATH_NOT_FOUND;
            size_t const cwc = RTUtf16Len(&wszPath[0]);
            if (    !GetEnvironmentVariableW(L"HOMEPATH", &wszPath[cwc], RTPATH_MAX - (DWORD)cwc)
                ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
                ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
                return VERR_PATH_NOT_FOUND;
        }
    }

    /*
     * Convert and return.
     */
    return RTUtf16ToUtf8Ex(&wszPath[0], RTSTR_MAX, &pszPath, cchPath, NULL);
}
/**
 * Converts the name from UTF-16 to UTF-8.
 *
 * Fortunately, the names are relative to the directory, so we won't have to do
 * any sweaty path style coversion. :-)
 *
 * @returns IPRT status code
 * @param   pThis       The directory instance data.
 * @param   cbName      The file name length in bytes.
 * @param   pwsName     The file name, not terminated.
 */
static int rtDirNtConvertName(PRTDIR pThis, uint32_t cbName, PCRTUTF16 pwsName)
{
    int rc = RTUtf16ToUtf8Ex(pwsName, cbName / 2, &pThis->pszName, pThis->cbNameAlloc, &pThis->cchName);
    if (RT_SUCCESS(rc))
    {
        if (!pThis->cbNameAlloc)
            pThis->cbNameAlloc = pThis->cchName + 1;
    }
    else if (rc == VERR_BUFFER_OVERFLOW)
    {
        RTStrFree(pThis->pszName);
        pThis->pszName = NULL;
        pThis->cbNameAlloc = 0;

        rc = RTUtf16ToUtf8Ex(pwsName, cbName / 2, &pThis->pszName, pThis->cbNameAlloc, &pThis->cchName);
        if (RT_SUCCESS(rc))
            pThis->cbNameAlloc = pThis->cchName + 1;
    }
    Assert(RT_SUCCESS(rc) ? pThis->pszName != NULL : pThis->pszName == NULL);
    return rc;
}
RTDECL(int) RTPathGetCurrentOnDrive(char chDrive, char *pszPath, size_t cbPath)
{
    WCHAR wszInput[4];
    wszInput[0] = chDrive;
    wszInput[1] = ':';
    wszInput[2] = '\0';

    int rc;
    RTUTF16 wszFullPath[RTPATH_MAX];
    if (GetFullPathNameW(wszInput, RTPATH_MAX, wszFullPath, NULL))
        rc = RTUtf16ToUtf8Ex(&wszFullPath[0], RTSTR_MAX, &pszPath, cbPath, NULL);
    else
        rc = RTErrConvertFromWin32(GetLastError());
    return rc;
}
/**
 * Get the absolute path (no symlinks, no . or .. components), doesn't have to exit.
 *
 * @returns iprt status code.
 * @param   pszPath         The path to resolve.
 * @param   pszAbsPath      Where to store the absolute path.
 * @param   cchAbsPath      Size of the buffer.
 */
RTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cchAbsPath)
{
    /*
     * Validation.
     */
    AssertPtr(pszAbsPath);
    AssertPtr(pszPath);
    if (RT_UNLIKELY(!*pszPath))
        return VERR_INVALID_PARAMETER;

    /*
     * Convert to UTF-16, call Win32 API, convert back.
     */
    LPWSTR pwszPath;
    int rc = RTStrToUtf16(pszPath, &pwszPath);
    if (!RT_SUCCESS(rc))
        return (rc);

    LPWSTR pwszFile; /* Ignored */
    RTUTF16 wsz[RTPATH_MAX];
    rc = GetFullPathNameW(pwszPath, RT_ELEMENTS(wsz), &wsz[0], &pwszFile);
    if (rc > 0 && rc < RT_ELEMENTS(wsz))
    {
        size_t cch;
        rc = RTUtf16ToUtf8Ex(&wsz[0], RTSTR_MAX, &pszAbsPath, cchAbsPath, &cch);
        if (RT_SUCCESS(rc))
        {
# if 1 /** @todo This code is completely bonkers. */
            /*
             * Remove trailing slash if the path may be pointing to a directory.
             * (See posix variant.)
             */
            if (    cch > 1
                &&  RTPATH_IS_SLASH(pszAbsPath[cch - 1])
                &&  !RTPATH_IS_VOLSEP(pszAbsPath[cch - 2])
                &&  !RTPATH_IS_SLASH(pszAbsPath[cch - 2]))
                pszAbsPath[cch - 1] = '\0';
# endif
        }
    }
    else if (rc <= 0)
        rc = RTErrConvertFromWin32(GetLastError());
    else
        rc = VERR_FILENAME_TOO_LONG;

    RTUtf16Free(pwszPath);
    return rc;
}
示例#12
0
DECLHIDDEN(int) rtProcInitExePath(char *pszPath, size_t cchPath)
{
    /*
     * Query the image name from the dynamic linker, convert and return it.
     */
    WCHAR  wsz[RTPATH_MAX];
    HMODULE hExe = GetModuleHandle(NULL);
    if (GetModuleFileNameW(hExe, wsz, RTPATH_MAX))
    {
        int rc = RTUtf16ToUtf8Ex(wsz, RTSTR_MAX, &pszPath, cchPath, NULL);
        AssertRCReturn(rc, rc);
        return VINF_SUCCESS;
    }

    DWORD err = GetLastError();
    int rc = RTErrConvertFromWin32(err);
    AssertMsgFailed(("%Rrc %d\n", rc, err));
    return rc;
}
示例#13
0
RTDECL(int) RTPathGetCurrent(char *pszPath, size_t cchPath)
{
    int rc;

    /*
     * GetCurrentDirectory may in some cases omit the drive letter, according
     * to MSDN, thus the GetFullPathName call.
     */
    RTUTF16 wszCurPath[RTPATH_MAX];
    if (GetCurrentDirectoryW(RTPATH_MAX, wszCurPath))
    {
        RTUTF16 wszFullPath[RTPATH_MAX];
        if (GetFullPathNameW(wszCurPath, RTPATH_MAX, wszFullPath, NULL))
            rc = RTUtf16ToUtf8Ex(&wszFullPath[0], RTSTR_MAX, &pszPath, cchPath, NULL);
        else
            rc = RTErrConvertFromWin32(GetLastError());
    }
    else
        rc = RTErrConvertFromWin32(GetLastError());
    return rc;
}
示例#14
0
HRESULT HostDnsServiceWin::updateInfo()
{
    HostDnsInformation info;

    LONG lrc;
    int rc;

    std::string strDomain;
    std::string strSearchList;  /* NB: comma separated, no spaces */


    /*
     * We ignore "DhcpDomain" key here since it's not stable.  If
     * there are two active interfaces that use DHCP (in particular
     * when host uses OpenVPN) then DHCP ACKs will take turns updating
     * that key.  Instead we call GetAdaptersAddresses() below (which
     * is what ipconfig.exe seems to do).
     */
    for (DWORD regIndex = 0; /**/; ++regIndex) {
        char keyName[256];
        DWORD cbKeyName = sizeof(keyName);
        DWORD keyType = 0;
        char keyData[1024];
        DWORD cbKeyData = sizeof(keyData);

        lrc = RegEnumValueA(m->hKeyTcpipParameters, regIndex,
                            keyName, &cbKeyName, 0,
                            &keyType, (LPBYTE)keyData, &cbKeyData);

        if (lrc == ERROR_NO_MORE_ITEMS)
            break;

        if (lrc == ERROR_MORE_DATA) /* buffer too small; handle? */
            continue;

        if (lrc != ERROR_SUCCESS)
        {
            LogRel2(("HostDnsServiceWin: RegEnumValue error %d\n", (int)lrc));
            return E_FAIL;
        }

        if (keyType != REG_SZ)
            continue;

        if (cbKeyData > 0 && keyData[cbKeyData - 1] == '\0')
            --cbKeyData;     /* don't count trailing NUL if present */

        if (RTStrICmp("Domain", keyName) == 0)
        {
            strDomain.assign(keyData, cbKeyData);
            LogRel2(("HostDnsServiceWin: Domain=\"%s\"\n", strDomain.c_str()));
        }
        else if (RTStrICmp("DhcpDomain", keyName) == 0)
        {
            std::string strDhcpDomain(keyData, cbKeyData);
            LogRel2(("HostDnsServiceWin: DhcpDomain=\"%s\"\n", strDhcpDomain.c_str()));
        }
        else if (RTStrICmp("SearchList", keyName) == 0)
        {
            strSearchList.assign(keyData, cbKeyData);
            LogRel2(("HostDnsServiceWin: SearchList=\"%s\"\n", strSearchList.c_str()));
        }
    }

    /* statically configured domain name */
    if (!strDomain.empty())
    {
        info.domain = strDomain;
        info.searchList.push_back(strDomain);
    }

    /* statically configured search list */
    if (!strSearchList.empty())
    {
        vappend(info.searchList, strSearchList, ',');
    }


    /*
     * When name servers are configured statically it seems that the
     * value of Tcpip\Parameters\NameServer is NOT set, inly interface
     * specific NameServer value is (which triggers notification for
     * us to pick up the change).  Fortunately, DnsApi seems to do the
     * right thing there.
     */
    DNS_STATUS status;
    PIP4_ARRAY pIp4Array = NULL;

    // NB: must be set on input it seems, despite docs' claim to the contrary.
    DWORD cbBuffer = sizeof(&pIp4Array);

    status = DnsQueryConfig(DnsConfigDnsServerList,
                            DNS_CONFIG_FLAG_ALLOC, NULL, NULL,
                            &pIp4Array, &cbBuffer);

    if (status == NO_ERROR && pIp4Array != NULL)
    {
        for (DWORD i = 0; i < pIp4Array->AddrCount; ++i)
        {
            char szAddrStr[16] = "";
            RTStrPrintf(szAddrStr, sizeof(szAddrStr), "%RTnaipv4", pIp4Array->AddrArray[i]);

            LogRel2(("HostDnsServiceWin: server %d: %s\n", i+1,  szAddrStr));
            info.servers.push_back(szAddrStr);
        }

        LocalFree(pIp4Array);
    }


    /**
     * DnsQueryConfig(DnsConfigSearchList, ...) is not implemented.
     * Call GetAdaptersAddresses() that orders the returned list
     * appropriately and collect IP_ADAPTER_ADDRESSES::DnsSuffix.
     */
    do {
        PIP_ADAPTER_ADDRESSES pAddrBuf = NULL;
        ULONG cbAddrBuf = 8 * 1024;
        bool fReallocated = false;
        ULONG err;

        pAddrBuf = (PIP_ADAPTER_ADDRESSES) malloc(cbAddrBuf);
        if (pAddrBuf == NULL)
        {
            LogRel2(("HostDnsServiceWin: failed to allocate %zu bytes"
                     " of GetAdaptersAddresses buffer\n",
                     (size_t)cbAddrBuf));
            break;
        }

        while (pAddrBuf != NULL)
        {
            ULONG cbAddrBufProvided = cbAddrBuf;

            err = GetAdaptersAddresses(AF_UNSPEC,
                                         GAA_FLAG_SKIP_ANYCAST
                                       | GAA_FLAG_SKIP_MULTICAST,
                                       NULL,
                                       pAddrBuf, &cbAddrBuf);
            if (err == NO_ERROR)
            {
                break;
            }
            else if (err == ERROR_BUFFER_OVERFLOW)
            {
                LogRel2(("HostDnsServiceWin: provided GetAdaptersAddresses with %zu"
                         " but asked again for %zu bytes\n",
                         (size_t)cbAddrBufProvided, (size_t)cbAddrBuf));

                if (RT_UNLIKELY(fReallocated)) /* what? again?! */
                {
                    LogRel2(("HostDnsServiceWin: ... not going to realloc again\n"));
                    free(pAddrBuf);
                    pAddrBuf = NULL;
                    break;
                }

                PIP_ADAPTER_ADDRESSES pNewBuf = (PIP_ADAPTER_ADDRESSES) realloc(pAddrBuf, cbAddrBuf);
                if (pNewBuf == NULL)
                {
                    LogRel2(("HostDnsServiceWin: failed to reallocate %zu bytes\n", (size_t)cbAddrBuf));
                    free(pAddrBuf);
                    pAddrBuf = NULL;
                    break;
                }

                /* try again */
                pAddrBuf = pNewBuf; /* cbAddrBuf already updated */
                fReallocated = true;
            }
            else
            {
                LogRel2(("HostDnsServiceWin: GetAdaptersAddresses error %d\n", err));
                free(pAddrBuf);
                pAddrBuf = NULL;
                break;
            }
        }

        if (pAddrBuf == NULL)
            break;

        for (PIP_ADAPTER_ADDRESSES pAdp = pAddrBuf; pAdp != NULL; pAdp = pAdp->Next)
        {
            LogRel2(("HostDnsServiceWin: %ls (status %u) ...\n",
                     pAdp->FriendlyName ? pAdp->FriendlyName : L"(null)",
                     pAdp->OperStatus));

            if (pAdp->OperStatus != IfOperStatusUp)
                continue;

            if (pAdp->DnsSuffix == NULL || *pAdp->DnsSuffix == L'\0')
                continue;

            char *pszDnsSuffix = NULL;
            rc = RTUtf16ToUtf8Ex(pAdp->DnsSuffix, RTSTR_MAX,
                                 &pszDnsSuffix, 0, /* allocate */
                                 NULL);
            if (RT_FAILURE(rc))
            {
                LogRel2(("HostDnsServiceWin: failed to convert DNS suffix \"%ls\": %Rrc\n",
                        pAdp->DnsSuffix, rc));
                continue;
            }

            AssertContinue(pszDnsSuffix != NULL);
            AssertContinue(*pszDnsSuffix != '\0');
            LogRel2(("HostDnsServiceWin: ... suffix = \"%s\"\n", pszDnsSuffix));

            vappend(info.searchList, pszDnsSuffix);
            RTStrFree(pszDnsSuffix);
        }

        free(pAddrBuf);
    } while (0);


    if (info.domain.empty() && !info.searchList.empty())
        info.domain = info.searchList[0];

    if (info.searchList.size() == 1)
        info.searchList.clear();

    HostDnsMonitor::setInfo(info);

    return S_OK;
}
示例#15
0
/**
 * Services the  RTSYSOSINFO_PRODUCT, RTSYSOSINFO_RELEASE
 * and RTSYSOSINFO_SERVICE_PACK requests.
 *
 * @returns See RTSystemQueryOSInfo.
 * @param   enmInfo         See RTSystemQueryOSInfo.
 * @param   pszInfo         See RTSystemQueryOSInfo.
 * @param   cchInfo         See RTSystemQueryOSInfo.
 */
static int rtSystemWinQueryOSVersion(RTSYSOSINFO enmInfo, char *pszInfo, size_t cchInfo)
{
    /*
     * Make sure it's terminated correctly in case of error.
     */
    *pszInfo = '\0';

    /*
     * Check that we got the windows version at init time.
     */
    AssertReturn(g_WinOsInfoEx.dwOSVersionInfoSize, VERR_WRONG_ORDER);

    /*
     * Service the request.
     */
    char szTmp[512];
    szTmp[0] = '\0';
    switch (enmInfo)
    {
        /*
         * The product name.
         */
        case RTSYSOSINFO_PRODUCT:
        {
            switch (g_enmWinVer)
            {
                case kRTWinOSType_95:           strcpy(szTmp, "Windows 95"); break;
                case kRTWinOSType_95SP1:        strcpy(szTmp, "Windows 95 (Service Pack 1)"); break;
                case kRTWinOSType_95OSR2:       strcpy(szTmp, "Windows 95 (OSR 2)"); break;
                case kRTWinOSType_98:           strcpy(szTmp, "Windows 98"); break;
                case kRTWinOSType_98SP1:        strcpy(szTmp, "Windows 98 (Service Pack 1)"); break;
                case kRTWinOSType_98SE:         strcpy(szTmp, "Windows 98 (Second Edition)"); break;
                case kRTWinOSType_ME:           strcpy(szTmp, "Windows Me"); break;
                case kRTWinOSType_NT351:        strcpy(szTmp, "Windows NT 3.51"); break;
                case kRTWinOSType_NT4:          strcpy(szTmp, "Windows NT 4.0"); break;
                case kRTWinOSType_2K:           strcpy(szTmp, "Windows 2000"); break;
                case kRTWinOSType_XP:
                    strcpy(szTmp, "Windows XP");
                    if (g_WinOsInfoEx.wSuiteMask & VER_SUITE_PERSONAL)
                        strcat(szTmp, " Home");
                    if (    g_WinOsInfoEx.wProductType == VER_NT_WORKSTATION
                        && !(g_WinOsInfoEx.wSuiteMask & VER_SUITE_PERSONAL))
                        strcat(szTmp, " Professional");
#if 0 /** @todo fixme */
                    if (GetSystemMetrics(SM_MEDIACENTER))
                        strcat(szTmp, " Media Center");
#endif
                    break;

                case kRTWinOSType_2003:         strcpy(szTmp, "Windows 2003"); break;
                case kRTWinOSType_VISTA:
                {
                    strcpy(szTmp, "Windows Vista");
                    rtSystemWinAppendProductType(szTmp);
                    break;
                }
                case kRTWinOSType_2008:         strcpy(szTmp, "Windows 2008"); break;
                case kRTWinOSType_7:            strcpy(szTmp, "Windows 7"); break;
                case kRTWinOSType_2008R2:       strcpy(szTmp, "Windows 2008 R2"); break;
                case kRTWinOSType_8:            strcpy(szTmp, "Windows 8"); break;
                case kRTWinOSType_2012:         strcpy(szTmp, "Windows 2012"); break;
                case kRTWinOSType_81:           strcpy(szTmp, "Windows 8.1"); break;
                case kRTWinOSType_2012R2:       strcpy(szTmp, "Windows 2012 R2"); break;
                case kRTWinOSType_10:           strcpy(szTmp, "Windows 10"); break;
                case kRTWinOSType_2016:         strcpy(szTmp, "Windows 2016"); break;

                case kRTWinOSType_NT_UNKNOWN:
                    RTStrPrintf(szTmp, sizeof(szTmp), "Unknown NT v%u.%u",
                                g_WinOsInfoEx.dwMajorVersion, g_WinOsInfoEx.dwMinorVersion);
                    break;

                default:
                    AssertFailed();
                case kRTWinOSType_UNKNOWN:
                    RTStrPrintf(szTmp, sizeof(szTmp), "Unknown %d v%u.%u",
                                g_WinOsInfoEx.dwPlatformId, g_WinOsInfoEx.dwMajorVersion, g_WinOsInfoEx.dwMinorVersion);
                    break;
            }
            break;
        }

        /*
         * The release.
         */
        case RTSYSOSINFO_RELEASE:
        {
            RTStrPrintf(szTmp, sizeof(szTmp), "%u.%u.%u",
                        g_WinOsInfoEx.dwMajorVersion, g_WinOsInfoEx.dwMinorVersion, g_WinOsInfoEx.dwBuildNumber);
            break;
        }


        /*
         * Get the service pack.
         */
        case RTSYSOSINFO_SERVICE_PACK:
        {
            if (g_WinOsInfoEx.wServicePackMajor)
            {
                if (g_WinOsInfoEx.wServicePackMinor)
                    RTStrPrintf(szTmp, sizeof(szTmp), "%u.%u",
                                (unsigned)g_WinOsInfoEx.wServicePackMajor, (unsigned)g_WinOsInfoEx.wServicePackMinor);
                else
                    RTStrPrintf(szTmp, sizeof(szTmp), "%u",
                                (unsigned)g_WinOsInfoEx.wServicePackMajor);
            }
            else if (g_WinOsInfoEx.szCSDVersion[0])
            {
                /* just copy the entire string. */
                char *pszTmp = szTmp;
                int rc = RTUtf16ToUtf8Ex(g_WinOsInfoEx.szCSDVersion, RT_ELEMENTS(g_WinOsInfoEx.szCSDVersion),
                                         &pszTmp, sizeof(szTmp), NULL);
                if (RT_SUCCESS(rc))
                    RTStrStripR(szTmp);
                else
                    szTmp[0] = '\0';
                AssertCompile(sizeof(szTmp) > sizeof(g_WinOsInfoEx.szCSDVersion));
            }
            else
            {
                switch (g_enmWinVer)
                {
                    case kRTWinOSType_95SP1:    strcpy(szTmp, "1"); break;
                    case kRTWinOSType_98SP1:    strcpy(szTmp, "1"); break;
                    default:
                        break;
                }
            }
            break;
        }

        default:
            AssertFatalFailed();
    }

    /*
     * Copy the result to the return buffer.
     */
    size_t cchTmp = strlen(szTmp);
    Assert(cchTmp < sizeof(szTmp));
    if (cchTmp < cchInfo)
    {
        memcpy(pszInfo, szTmp, cchTmp + 1);
        return VINF_SUCCESS;
    }
    memcpy(pszInfo, szTmp, cchInfo - 1);
    pszInfo[cchInfo - 1] = '\0';
    return VERR_BUFFER_OVERFLOW;
}
int vbsfPathGuestToHost(SHFLCLIENTDATA *pClient, SHFLROOT hRoot,
                        PCSHFLSTRING pGuestString, uint32_t cbGuestString,
                        char **ppszHostPath, uint32_t *pcbHostPathRoot,
                        uint32_t fu32Options,
                        uint32_t *pfu32PathFlags)
{
#ifdef VBOX_STRICT
    /*
     * Check that the pGuestPath has correct size and encoding.
     */
    if (ShflStringIsValidIn(pGuestString, cbGuestString, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)) == false)
    {
        LogFunc(("Invalid input string\n"));
        return VERR_INTERNAL_ERROR;
    }
#else
    NOREF(cbGuestString);
#endif

    /*
     * Resolve the root handle into a string.
     */
    uint32_t cbRootLen = 0;
    const char *pszRoot = NULL;
    int rc = vbsfMappingsQueryHostRootEx(hRoot, &pszRoot, &cbRootLen);
    if (RT_FAILURE(rc))
    {
        LogFunc(("invalid root\n"));
        return rc;
    }

    AssertReturn(cbRootLen > 0, VERR_INTERNAL_ERROR_2); /* vbsfMappingsQueryHostRootEx ensures this. */

    /*
     * Get the UTF8 string with the relative path provided by the guest.
     * If guest uses UTF-16 then convert it to UTF-8.
     */
    uint32_t    cbGuestPath = 0;        /* Shut up MSC */
    const char *pchGuestPath = NULL;    /* Ditto. */
    char *pchGuestPathAllocated = NULL; /* Converted from UTF-16. */
    if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
    {
        /* UTF-8 */
        cbGuestPath = pGuestString->u16Length;
        pchGuestPath = pGuestString->String.ach;
    }
    else
    {
        /* UTF-16 */

#ifdef RT_OS_DARWIN /* Misplaced hack! See todo! */
        uint32_t cwcSrc  = 0;
        PRTUTF16 pwszSrc = NULL;
        rc = vbsfNormalizeStringDarwin(&pGuestString->String.ucs2[0],
                                       pGuestString->u16Length / sizeof(RTUTF16),
                                       &pwszSrc, &cwcSrc);
#else
        uint32_t  const cwcSrc  = pGuestString->u16Length / sizeof(RTUTF16);
        PCRTUTF16 const pwszSrc = &pGuestString->String.ucs2[0];
#endif

        if (RT_SUCCESS(rc))
        {
            size_t cbPathAsUtf8 = RTUtf16CalcUtf8Len(pwszSrc);
            if (cbPathAsUtf8 >= cwcSrc)
            {
                /* Allocate buffer that will be able to contain the converted UTF-8 string. */
                pchGuestPathAllocated = (char *)RTMemAlloc(cbPathAsUtf8 + 1);
                if (RT_LIKELY(pchGuestPathAllocated != NULL))
                {
                    if (RT_LIKELY(cbPathAsUtf8))
                    {
                        size_t cchActual;
                        char *pszDst = pchGuestPathAllocated;
                        rc = RTUtf16ToUtf8Ex(pwszSrc, cwcSrc, &pszDst, cbPathAsUtf8 + 1, &cchActual);
                        AssertRC(rc);
                        AssertStmt(RT_FAILURE(rc) || cchActual == cbPathAsUtf8, rc = VERR_INTERNAL_ERROR_4);
                        Assert(strlen(pszDst) == cbPathAsUtf8);
                    }

                    if (RT_SUCCESS(rc))
                    {
                        /* Terminate the string. */
                        pchGuestPathAllocated[cbPathAsUtf8] = '\0';

                        cbGuestPath = (uint32_t)cbPathAsUtf8; Assert(cbGuestPath == cbPathAsUtf8);
                        pchGuestPath = pchGuestPathAllocated;
                    }
                }
                else
                {
                    rc = VERR_NO_MEMORY;
                }
            }
            else
            {
                AssertFailed();
                rc = VERR_INTERNAL_ERROR_3;
            }

#ifdef RT_OS_DARWIN
            RTMemFree(pwszSrc);
#endif
        }
    }

    char *pszFullPath = NULL;

    if (RT_SUCCESS(rc))
    {
        LogFlowFunc(("Root %s path %.*s\n", pszRoot, cbGuestPath, pchGuestPath));

        /*
         * Allocate enough memory to build the host full path from the root and the relative path.
         */
        const uint32_t cbFullPathAlloc = cbRootLen + 1 + cbGuestPath + 1; /* root + possible_slash + relative + 0 */
        pszFullPath = (char *)RTMemAlloc(cbFullPathAlloc);
        if (RT_LIKELY(pszFullPath != NULL))
        {
            /* Buffer for the verified guest path. */
            char *pchVerifiedPath = (char *)RTMemAlloc(cbGuestPath + 1);
            if (RT_LIKELY(pchVerifiedPath != NULL))
            {
                /* Init the pointer for the guest relative path. */
                uint32_t cbSrc = cbGuestPath;
                const char *pchSrc = pchGuestPath;

                /* Strip leading delimiters from the path the guest specified. */
                while (   cbSrc > 0
                       && *pchSrc == pClient->PathDelimiter)
                {
                    ++pchSrc;
                    --cbSrc;
                }

                /*
                 * Iterate the guest path components, verify each of them replacing delimiters with the host slash.
                 */
                char *pchDst = pchVerifiedPath;
                bool fLastComponentHasWildcard = false;
                for (; cbSrc > 0; --cbSrc, ++pchSrc)
                {
                    if (RT_LIKELY(*pchSrc != pClient->PathDelimiter))
                    {
                        if (RT_LIKELY(vbsfPathIsValidNameChar(*pchSrc)))
                        {
                            if (pfu32PathFlags && vbsfPathIsWildcardChar(*pchSrc))
                            {
                                fLastComponentHasWildcard = true;
                            }

                            *pchDst++ = *pchSrc;
                        }
                        else
                        {
                            rc = VERR_INVALID_NAME;
                            break;
                        }
                    }
                    else
                    {
                        /* Replace with the host slash. */
                        *pchDst++ = RTPATH_SLASH;

                        if (pfu32PathFlags && fLastComponentHasWildcard && cbSrc > 1)
                        {
                            /* Processed component has a wildcard and there are more characters in the path. */
                            *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_PREFIX;
                        }
                        fLastComponentHasWildcard = false;
                    }
                }

                if (RT_SUCCESS(rc))
                {
                    *pchDst++ = 0;

                    /* Construct the full host path removing '.' and '..'. */
                    rc = vbsfPathAbs(pszRoot, pchVerifiedPath, pszFullPath, cbFullPathAlloc);
                    if (RT_SUCCESS(rc))
                    {
                        if (pfu32PathFlags && fLastComponentHasWildcard)
                        {
                            *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_LAST;
                        }

                        /* Check if the full path is still within the shared folder. */
                        if (fu32Options & VBSF_O_PATH_CHECK_ROOT_ESCAPE)
                        {
                            if (!RTPathStartsWith(pszFullPath, pszRoot))
                            {
                                rc = VERR_INVALID_NAME;
                            }
                        }

                        if (RT_SUCCESS(rc))
                        {
                            /*
                             * If the host file system is case sensitive and the guest expects
                             * a case insensitive fs, then correct the path components casing.
                             */
                            if (    vbsfIsHostMappingCaseSensitive(hRoot)
                                && !vbsfIsGuestMappingCaseSensitive(hRoot))
                            {
                                const bool fWildCard = RT_BOOL(fu32Options & VBSF_O_PATH_WILDCARD);
                                const bool fPreserveLastComponent = RT_BOOL(fu32Options & VBSF_O_PATH_PRESERVE_LAST_COMPONENT);
                                rc = vbsfCorrectPathCasing(pClient, pszFullPath, strlen(pszFullPath),
                                                           fWildCard, fPreserveLastComponent);
                            }

                            if (RT_SUCCESS(rc))
                            {
                               LogFlowFunc(("%s\n", pszFullPath));

                               /* Return the full host path. */
                               *ppszHostPath = pszFullPath;

                               if (pcbHostPathRoot)
                               {
                                   /* Return the length of the root path without the trailing slash. */
                                   *pcbHostPathRoot = RTPATH_IS_SLASH(pszFullPath[cbRootLen - 1]) ?
                                                          cbRootLen - 1 : /* pszRoot already had the trailing slash. */
                                                          cbRootLen; /* pszRoot did not have the trailing slash. */
                               }
                            }
                        }
                    }
                    else
                    {
                        LogFunc(("vbsfPathAbs %Rrc\n", rc));
                    }
                }

                RTMemFree(pchVerifiedPath);
            }
            else
            {
                rc = VERR_NO_MEMORY;
            }
        }
        else
        {
            rc = VERR_NO_MEMORY;
        }
    }

    /*
     * Cleanup.
     */
    RTMemFree(pchGuestPathAllocated);

    if (RT_SUCCESS(rc))
    {
        return rc;
    }

    /*
     * Cleanup on failure.
     */
    RTMemFree(pszFullPath);

    LogFunc(("%Rrc\n", rc));
    return rc;
}