Solution to a problem nobody has: Changing Total Commander application icon

Maybe you are like me and tend to drag along your favorite Windows applications even though you switched away to a different operating system a while ago. Well, maybe not… Still, I couldn’t find any file manager for Linux or OS X that would work as well as Total Commander. So I keep running it via Wine and it works surprisingly well.

Having the standard application icon display on OS X is somewhat awkward however: with 32×32 pixels it is simply too small, one would need a significantly larger icon for it to fit nicely into the OS X user interface. Wine doesn’t allow configuring the icon however, the source code shows that it will read the icon from the application resource unconditionally. Well, not really a problem — changing resources in Windows applications is fairly easy.

All you need a new high-resolution icon in .ICO format (I liked the one by arrioch) and Resource Hacker. Open TOTALCMD.EXE with Resource Hacker, select the resource in the MAINICON icon group, right-click it and choose “Replace Resource” — select the new icon, save file (did you back up the original version?), done.

Now you can run your modified version. Isn’t it beautiful? Wait, what’s this message: “The TOTALCMD executable is corrupted, possible VIRUS! Totalcmd will close.”? Where did Total Commander go? A search quickly tells you that this is a security mechanism and cannot be disabled. Not a very useful security mechanism of course, we have year 2014 and viruses infecting executables are almost extinct. Still, Process Monitor confirms that Total Commander reads in its entire executable from disk and probably builds a hash sum to verify that it hasn’t been change.

But what if one could make sure that the executable that is being read is the original Total Commander executable? After going through a few options I settled with the most simple one: have a launcher executable that will start the modified Total Commander executable and immediately replace it with the original one. Normally that wouldn’t work due to Windows locking the files. But my operating system isn’t Windows, it’s a Unix merely pretending to be Windows. So if the launcher runs a Unix command then that command will be able to replace files regardless of locks. Assuming that TOTALCMD.EXE is the original binary and TOTALCMD2.EXE the modified one, here is some code:

#include <windows.h>

DWORD Run(LPWSTR command, BOOL wait)
{
  STARTUPINFOW si;
  PROCESS_INFORMATION pi;
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);
  ZeroMemory(&pi, sizeof(pi));
  si.dwFlags = STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_MAXIMIZE;

  CreateProcessW(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
  DWORD processId = GetProcessId(pi.hProcess);

  if (wait)
  {
    WaitForSingleObject(pi.hProcess, INFINITE);

    // For some reason, just waiting for the process to terminate isn't enough
    Sleep(500);
  }

  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);
  return processId;
}

int CALLBACK WinMain(
  _In_  HINSTANCE hInstance,
  _In_  HINSTANCE hPrevInstance,
  _In_  LPSTR lpCmdLine,
  _In_  int nCmdShow
)
{
  // Change current directory to the directory of our executable
  WCHAR path[MAX_PATH];
  GetModuleFileNameW(NULL, path, MAX_PATH);
  int pos = lstrlenW(path);
  while (pos >= 0 && path[pos] != L'\\')
    pos--;
  if (pos >= 0)
    path[pos] = 0;
  SetCurrentDirectoryW(path);

  Run(L"/bin/sh -c \"cp TOTALCMD2.EXE TOTALCMDTMP.EXE\"", TRUE);
  DWORD processId = Run(L"TOTALCMDTMP.EXE", FALSE);

  // Use debugging API to suspend the process while we are replacing the file
  DebugActiveProcess(processId);
  Run(L"/bin/sh -c \"cp TOTALCMD.EXE TOTALCMDTMP.EXE\"", TRUE);
  DebugActiveProcessStop(processId);
}

You have to compile this code on Windows or use a cross-compiler like MinGW (I did the former so I don’t really know whether you will hit any issues using a cross-compiler). Surprisingly, it actually works — you get Total Commander with a better icon yet the security check will still see the original binary and won’t complain.

Comments

  • this just in

    resource hacker seems to be a bit long in the tooth

    why aren’t you using parallels?

    Wladimir Palant

    I am new to OS X and didn’t have a chance to look at Parallels yet. My Wine setup was simply migrated from Linux. Also, the price tag associated with Parallels is a significant barrier to entry for something that works fine as it is (probably better, I doubt that Parallels lets you run OS X commands from a Windows application).