如何正确调用 UrlCanonicalize API 函数

How do I call the UrlCanonicalize API function correctly?

本文关键字:API 函数 UrlCanonicalize 调用 何正确      更新时间:2023-10-16
HRESULT UrlCanonicalize(
  _In_     PCTSTR pszUrl,
  _Out_    PTSTR pszCanonicalized,
  _Inout_  DWORD *pcchCanonicalized,
  DWORD dwFlags
);

例:

LPCTSTR pszURL  = URL.c_str();
LPSTR pszOutPut = new CHAR[ strUrl.length ];
DWORD* dwCount = new DWORD[  strUrl.length ];
hRes =  UrlCanonicalize( pszURL, pszOutPut,dwCount, URL_ESCAPE_UNSAFE );

输出:

E_INVALIDARG

此 API 失败,每次我尝试调用它时都会返回E_INVALIDARG。请给我一个工作代码片段来调用UrlCanonicalize函数。

如果您了解C++语言,该函数的 SDK 文档几乎会告诉您您需要了解的所有内容:

  • 你给它传递一个包含你的 URL 的 C 样式的 nul 终止字符串。
  • 将其指针传递给缓冲区以接收输出字符串。
  • 您可以向它传递一个或多个自定义函数行为的标志。
  • 最后,它会返回一个HRESULT值,这是一个错误代码。如果成功,该值将S_OK 。如果失败,它将是其他错误代码。

它的工作原理是这样的:

std::wstring originalURL(L"http://www.example.com/hello/cruel/../world/");
// Allocate a buffer of the appropriate length.
// It needs to be at least as long as the input string.
std::wstring canonicalURL(originalURL.length() + 1, L'');
DWORD length = originalURL.length() + 1;
// Call the function to modify the string.
HRESULT hr = UrlCanonicalize(originalURL.c_str(), // input string
                             &canonicalURL[0],    // buffer
                             &length,             // pointer to a DWORD that contains the length of the buffer
                             URL_UNESCAPE | URL_ESCAPE_UNSAFE);
if (SUCCEEDED(hr))
{
    // The function succeeded.
    // Your canonicalized URL is in the canonicalURL string.
    MessageBox(nullptr, canonicalURL.c_str(), L"The URL is:", MB_OK);   
}
else
{
    // The function failed.
    // The hr variable contains the error code.
    throw std::runtime_error("The UrlCanonicalize function failed.");
}

如果要确保缓冲区足够长(并避免处理该错误(,请在分配缓冲区时使用常量INTERNET_MAX_URL_LENGTH(在 WinInet.h 中声明(:

std::wstring canonicalURL(INTERNET_MAX_URL_LENGTH, L'');
DWORD length = INTERNET_MAX_URL_LENGTH;

您尝试的代码有几个问题:

  1. 您错误地初始化了dwCount变量。该函数需要一个指针,但这并不意味着您应该将变量声明为指针。你也不想要一个数组;这是一个DWORD值。所以你需要把它声明为一个正DWORD,然后使用地址运算符(&(给函数传递一个指向该变量的指针。现在,您正在传递函数垃圾,因此它失败了。

  2. 你使用的是 C 样式字符串,C++代码中应避免使用。使用 C++ 字符串类(std::wstring 用于 Windows 代码(,该类异常安全并为您管理内存。如您所知,c_str() 成员函数使您可以像所有 C API 一样轻松访问 C 样式的 nul 终止字符串。这工作正常,您不需要自己使用原始字符数组。尽可能避免new

可能,第三个问题是您尝试使用 C++ 字符串类型 std::string 而不是 std::wstring 。前者是 8 位字符串类型,在 Windows 环境中不支持 Unicode。你想要std::wstring,这是一个支持 Unicode 的宽字符串。这是所有 Windows API 函数所期望的,如果你为项目定义了UNICODE符号(默认情况下是(。

你来了:

LPCTSTR pszURL = URL.c_str();
DWORD nOutputLength = strUrl.length * 2 + 32;
LPTSTR pszOutPut = new TCHAR[nOutputLength];
hRes = UrlCanonicalize( pszURL, pszOutPut, &nOutputLength, URL_ESCAPE_UNSAFE);

在第三个参数上,您提供了垃圾而不是指向初始化值的指针,因此您有 API 故障返回。MSDN 为您提供了一切:

指向一个值的指针,该值在输入时设置为 pszCanonicalized 缓冲区中的字符数。