The URLUnEscapse function will do it for you but it requires Windows 2000 or IE5 to be installed see following MSDN docs
UrlUnEscape
[This is preliminary documentation and subject to change.]
Converts escape sequences back into ordinary characters.
HRESULT UrlUnEscape(
LPTSTR pszURL,
LPTSTR pszUnEscaped,
LPDWORD pcchUnEscaped,
DWORD dwFlags
);
Parameters
pszURL
[in/out] Pointer to a NULL-terminated string with the URL. If dwFlags is set to URL_UNESCAPE_INPLACE, the converted string is returned through this parameter.
pszUnEscaped
[out] Pointer to a NULL-terminated string containing the unescaped version of pszURL. If URL_UNESCAPE_INPLACE is set in dwFlags, this parameter is ignored.
pcchUnEscaped
[in/out] Number of characters in the buffer pointed to by pszEscaped. On entry, the value pcchEscaped points to is set to the size of the buffer. When the function returns, the value pcchEscaped points to is set to the number of characters written to that buffer, not counting the terminating NULL character. If an E_POINTER error code is returned, the buffer was too small, and the value pcchEscaped points to is set to the required number of characters in the buffer. If any other errors are returned, the value that pcchEscaped points to is undefined.
dwFlags
[in] Flags that control which characters are unescaped. It can be a combination of the following flags. Flag Description
URL_DONT_UNESCAPE_EXTRA_INFO Don't convert the # or ? character, or any characters following them in the string.
URL_UNESCAPE_INPLACE Use pszURL to return the converted string instead of pszUnEscaped.
Return Values
Returns an OLE success code if successful. If the URL_UNESCAPE_INPLACE flag is not set, the value pointed to by pcchUnEscaped will be set to the number of characters in the output buffer pointed to by pszEscaped. Returns E_POINTER if the URL_UNESCAPE_INPLACE flag is not set and the output buffer is too small. The pcchUnEscaped parameter will be set to the required buffer size. Otherwise, returns an OLE error value.