ERROR_INTERNET_EXTENDED_ERROR

Quick recap of something I missed yesterday - when uploading content to my site, my tool will sometimes throw an exception and call it quits. Why?

I remembered vaguely that this was an issue, and one that I didn't care about. It had something to do with remote subdirectories. My first site had one top-level directory per year, and so it was a very rare thing to create a new one - presumably I did it by hand, and saved me the time to do handle properly..

Running in the debugger, I quickly found out that I was simply propagating errors from FtpFindFirstFile. It turns out that the path from lpszSearchFile was causing the problem by not existing - instead of an empty enumeration, I was getting an error code.

The proper way to handle this is to look for ERROR_INTERNET_EXTENDED_ERROR in GetLastError() after the call, and if found, invoke InternetGetLastResponseInfo.

That returns a second error code, but unfortunately that's not populated for FTP. Instead, I decided to check for the output text, which includes the FTP messages, as a way to sniff for it. Not foolproof, but I can always create the directory by hand, and it helps me with my own FTP server.

Anyway, if you're curious, here goes.


private bool FileExists(WinInet.HINTERNET connection, string path) {

WinInet.HINTERNET request; // Enumeration request.
WinInet.WIN32_FIND_DATA findFileData; // Data result.

request = WinInet.FtpFindFirstFile(connection, path, out findFileData, 0, IntPtr.Zero);
if (request.IsInvalid) {
 int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
 if (error != 0 && error != WinInet.ERROR_NO_MORE_FILES) {
  if (error == WinInet.ERROR_INTERNET_EXTENDED_ERROR) {
   uint err;
   uint len = 0;
   WinInet.InternetGetLastResponseInfo(out err, null, ref len);
   StringBuilder sb = new StringBuilder((int)len);
   if (WinInet.InternetGetLastResponseInfo(out err, sb, ref len)) {
    string errorString = sb.ToString();
    if (errorString.Contains("No such file or directory")) {
     return false;
    }
    throw new InvalidOperationException(sb.ToString());
   }
   throw new System.ComponentModel.Win32Exception(error);
  } else {
   throw new System.ComponentModel.Win32Exception(error);
  }
 }
 return false;
} else {
 WinInet.InternetCloseHandle(request);
 return true;
}

}

I think I'll invest in a code formatter in the near future ...

Tags:  winineterrorsdotnetnet

Home