如何正确调用UrlCanonicalize API函数?

时间:2013-08-16 11:10:21

标签: c++ winapi

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时,此API都会失败并返回E_INVALIDARG。请给我一个工作代码段来调用UrlCanonicalize函数。

2 个答案:

答案 0 :(得分:2)

如果您了解C ++语言,the SDK documentation for the function几乎可以告诉您需要了解的所有内容:

  • 您传递一个C风格的以空字符结尾的字符串,其中包含您的网址。
  • 您将指针传递给缓冲区以接收输出字符串。
  • 您传递一个或多个自定义函数行为的标志。
  • 最后,它会返回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'\0');
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'\0');
DWORD length = INTERNET_MAX_URL_LENGTH;

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

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

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

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

答案 1 :(得分:0)

你走了:

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 has it all适合您:

  

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