title: Mingw produces x86 program which only successfully runs as Administrator- x64 and VS(x86 and x64) versions fine
body: <p>I was taking a look at this Github project: <a href="https://github.com/LloydLabs/delete-self-poc" rel="nofollow noreferrer">https://github.com/LloydLabs/delete-self-poc</a></p>
  <p>This project uses the SetFileInformationByHandle API (<a href="https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfileinformationbyhandle" rel="nofollow noreferrer">https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfileinformationbyhandle</a>) in a somewhat creative way to allow the deletion from disk of a locked file.  I am attempting to implement this as part of a larger program, however I have ran into an issue when compiling for x86.  I use mingw-w64 on a debian machine to compile my program and when doing compatibility checks for x86, I found a very strange issue.</p>
  <pre><code>#include &quot;main.h&quot;
  
  static
  HANDLE
  ds_open_handle(
      PWCHAR pwPath
  )
  {
      return CreateFileW(pwPath, DELETE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  }
  
  static
  BOOL
  ds_rename_handle(
      HANDLE hHandle
  )
  {
      FILE_RENAME_INFO fRename;
      RtlSecureZeroMemory(&amp;fRename, sizeof(fRename));
  
      // set our FileNameLength and FileName to DS_STREAM_RENAME
      LPWSTR lpwStream = DS_STREAM_RENAME;
      fRename.FileNameLength = sizeof(lpwStream);
      RtlCopyMemory(fRename.FileName, lpwStream, sizeof(lpwStream));
  
      return SetFileInformationByHandle(hHandle, FileRenameInfo, &amp;fRename, sizeof(fRename) + sizeof(lpwStream));
  }
  
  static
  BOOL 
  ds_deposite_handle(
      HANDLE hHandle
  )
  {
      // set FILE_DISPOSITION_INFO::DeleteFile to TRUE
      FILE_DISPOSITION_INFO fDelete;
      RtlSecureZeroMemory(&amp;fDelete, sizeof(fDelete));
  
      fDelete.DeleteFile = TRUE;
  
      return SetFileInformationByHandle(hHandle, FileDispositionInfo, &amp;fDelete, sizeof(fDelete));
  }
  
  int
  main(
      int argc,
      char** argv
  )
  {
      WCHAR wcPath[MAX_PATH + 1];
      RtlSecureZeroMemory(wcPath, sizeof(wcPath));
  
      // get the path to the current running process ctx
      if (GetModuleFileNameW(NULL, wcPath, MAX_PATH) == 0)
      {
          DS_DEBUG_LOG(L&quot;failed to get the current module handle&quot;);
          return 0;
      }
  
      HANDLE hCurrent = ds_open_handle(wcPath);
      if (hCurrent == INVALID_HANDLE_VALUE)
      {
          DS_DEBUG_LOG(L&quot;failed to acquire handle to current running process&quot;);
          return 0;
      }
  
      // rename the associated HANDLE's file name
      DS_DEBUG_LOG(L&quot;attempting to rename file name&quot;);
      if (!ds_rename_handle(hCurrent))
      {
          DS_DEBUG_LOG(L&quot;failed to rename to stream&quot;);
          return 0;
      }
  
      DS_DEBUG_LOG(L&quot;successfully renamed file primary :$DATA ADS to specified stream, closing initial handle&quot;);
      CloseHandle(hCurrent);
  
      // open another handle, trigger deletion on close
      hCurrent = ds_open_handle(wcPath);
      if (hCurrent == INVALID_HANDLE_VALUE)
      {
          DS_DEBUG_LOG(L&quot;failed to reopen current module&quot;);
          return 0;
      }
  
      if (!ds_deposite_handle(hCurrent))
      {
          DS_DEBUG_LOG(L&quot;failed to set delete deposition&quot;);
          return 0;
      }
  
      // trigger the deletion deposition on hCurrent
      DS_DEBUG_LOG(L&quot;closing handle to trigger deletion deposition&quot;);
      CloseHandle(hCurrent);
  
      // verify we've been deleted
      if (PathFileExistsW(wcPath))
      {
          DS_DEBUG_LOG(L&quot;failed to delete copy, file still exists&quot;);
          return 0;
      }
  
      DS_DEBUG_LOG(L&quot;successfully deleted self from disk&quot;);
      return 1;
  }
  </code></pre>
  <p>When compiling the base code found in the linked repository (and shown above) as x86, attempting to run the program fails at the SetFileInformationByHandle call in the ds_rename_handle function. Calling GetLastError() returns 123:</p>
  <pre><code>ERROR_INVALID_NAME
  
  123 (0x7B)
  
  The filename, directory name, or volume label syntax is incorrect.
  </code></pre>
  <p>The very bizarre part is that the program succeeds when ran from an Administrator prompt.  Even stranger, compiling the same code for x64 works both in a normal and an Administrator prompt.</p>
  <p>As a sanity check I copied the code verbatim over to VS2019 and compiled there, and the resulting x86 program was able to run without Administrator privileges.</p>
  <p>The only changes to the source code made on the debian system were made in the header file:</p>
  <pre><code>#pragma once
  
  #pragma comment(lib, &quot;Shlwapi.lib&quot;)
  
  #include &lt;Windows.h&gt;
  #include &lt;shlwapi.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  
  #define DS_STREAM_RENAME L&quot;:wtfbbq&quot;
  #define DS_DEBUG_LOG(msg) wprintf(L&quot;[LOG] - %s\n&quot;, msg)
  </code></pre>
  <p>Where &lt;Windows.h&gt; was changed to &lt;windows.h&gt; and the DS_DEBUG_LOG line changed to %ls so that the entire log message would print.</p>
  <p>The GCC command used to compile for x86 was:</p>
  <pre><code>i686-w64-mingw32-gcc main.c -o delete32.exe -s -DUNICODE -Os -lshlwapi
  </code></pre>
  <p>I have tried removing all switches and compiling and it still fails.</p>
  <p>As a note, the shlwapi library is only required for the very last call in main(), PathFileExistsW.  I have commented out that portion and removed shlwapi from imports and from the gcc command to no effect.</p>
  <p>The x64 gcc command which succeeded was:</p>
  <pre><code>x86_64-w64-mingw32-gcc main.c -o delete32.exe -s -DUNICODE -Os -lshlwapi
  </code></pre>
  <p>In the issues tab of the github repo there are some mentions of errors in the code which I have looked at separately.  However I would desperately like to know why mingw is causing an issue with the 32 bit version of this program.  Unfortunately &quot;just compile with VS&quot; isn't an option, as I use a program to generate and compile the program that this bit of code will be part of on my linux machine.</p>
  <p>Thanks for any insight.</p>