title: FindNextFile ERROR_INVALID_NAME
body: <p>I'm trying to use the WINAPI functions <strong>FindFirstFile</strong> and <strong>FindNextFile</strong>.
  However, I'm experiencing some issues.</p>
  <p>When I first call the function FindFirstFile it works fine. I've got a valid handler and the first folder/file name is properly populated inside the WIN32_FIND_DATA structure. No error is found with GetLastError.</p>
  <p>Then, I call FindNextFile which returns true as there are more folders in the directory I'm scanning. But I can't retrieve the next folder/file name and  GetLastError returns 123 (0x7B) ERROR_INVALID_NAME.
  I'm a little confused as it says in the official documentation that if an error occurs it should return 0.</p>
  <p><a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364428(v=vs.85).aspx" rel="nofollow noreferrer">https://msdn.microsoft.com/en-us/library/windows/desktop/aa364428(v=vs.85).aspx</a></p>
  <blockquote>
  <p>Return value</p>
  <p>If the function succeeds, the return value is nonzero and the lpFindFileData parameter contains information about the next file or directory found.
  <strong>If the function fails, the return value is zero and the contents of lpFindFileData are indeterminate. To get extended error information, call the GetLastError function.</strong>
  If the function fails because no more matching files can be found, the GetLastError function returns ERROR_NO_MORE_FILES.</p>
  </blockquote>
  <p>I'm using .NET 4.5.1 and Visual Studio 2013 on Windows 7 x64.
  Here is a sample code.</p>
  <pre><code>[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
  public struct WIN32_FIND_DATA
  {
      public uint dwFileAttributes;
      public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
      public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
      public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
      public uint nFileSizeHigh;
      public uint nFileSizeLow;
      public uint dwReserved0;
      public uint dwReserved1;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
      public string cFileName;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
      public string cAlternateFileName;
  }
  </code></pre>
  <p>...</p>
  <pre><code>    [DllImport(&quot;Kernel32.dll&quot;, EntryPoint = &quot;FindFirstFile&quot;, SetLastError = true)]
      public static extern IntPtr FindFirstFile(string lpFileName, ref WIN32_FIND_DATA lpFindFileData);
  
      [return: MarshalAs(UnmanagedType.Bool)]
      [DllImport(&quot;Kernel32.dll&quot;, EntryPoint = &quot;FindFirstFile&quot;, SetLastError = true)]
      public static extern bool FindNextFile(IntPtr hFindFile, ref WIN32_FIND_DATA lpFindFileData);
  
      [return: MarshalAs(UnmanagedType.Bool)]
      [DllImport(&quot;Kernel32.dll&quot;, EntryPoint = &quot;FindClose&quot;, SetLastError = true)]
      public static extern bool FindClose(IntPtr hFindFile);
  </code></pre>
  <p>...</p>
  <pre><code>public static void Test()
  {
      WIN32_FIND_DATA metaDataFile = new WIN32_FIND_DATA();
  
      IntPtr nextHandle = FileScanner.FindFirstFile(&quot;C:\\*&quot;, ref metaDataFile);
      Console.WriteLine(Marshal.GetLastWin32Error()); // This equals 0x0 ERROR_SUCCESS
      Console.WriteLine(metaDataFile.cFileName); // This equals $Recycle.Bin
  
      /* Check invalid handler */
      if (nextHandle != new IntPtr(-1L))
      {
          bool moreFiles = true;
          while (moreFiles)
          {
              moreFiles = FileScanner.FindNextFile(nextHandle, ref metaDataFile);
              Console.WriteLine(Marshal.GetLastWin32Error()); // This equals 0x7B ERROR_INVALID_NAME
              Console.WriteLine(metaDataFile.cFileName); // This equals $Recycle.Bin and this value never change. 
          }
      
      FindClose(nextHandle);
      }
  }
  </code></pre>
  <p>For some reason, moreFiles is always true and GetLastError returns ERROR_INVALID_NAME ...</p>
  <p>If you need any details please ask me.
  Any help would really be appreciated !</p>