////////////////////////////////////////////////////////
// SelfDelete() invokes the command interpreter as define by
// the environment variable "COMSPEC". This varies with the
// OS: Win9x/ME use COMMAND.COM; WinNT/2K/XP use CMD.EXE.
//
// The module filename (szModule) needs to be converted into
// its short 8.3 name to change any extended unicode chars
// into OEM equivalents.
//
// SelfDelete() should be called only at the program's exit.
// Make sure all processes/threads have finished and all
// handles are closed before calling the function.
////////////////////////////////////////////////////////
// Author: Tony Varnas
#include <windows.h>
#include <shlobj.h>
#include <shellapi.h>
BOOL SelfDelete(void)
{
SHELLEXECUTEINFO sei;
TCHAR szModule [MAX_PATH],
szComspec[MAX_PATH],
szParams [MAX_PATH];
// get file path names
if((GetModuleFileName(0,szModule,MAX_PATH)!=0) &&
(GetShortPathName(szModule,szModule,MAX_PATH)!=0) &&
(GetEnvironmentVariable("COMSPEC",szComspec,MAX_PATH)!=0))
{
// create comspec parameters
lstrcpy(szParams,"/c del "); // run a single command to...
lstrcat(szParams, szModule); //
del(ete) module file and...
lstrcat(szParams, " > nul"); // output results to nowhere
// set struct members
sei.cbSize = sizeof(sei);
sei.hwnd = 0;
sei.lpVerb = "Open";
sei.lpFile= szComspec;
sei.lpParameters = szParams;
sei.lpDirectory = 0;
sei.nShow = SW_HIDE;
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
// give all CPU cycles to current process
SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);
// execute command shell
if(ShellExecuteEx(&sei))
{
// freeze command shell process
SetPriorityClass(sei.hProcess,IDLE_PRIORITY_CLASS);
SetProcessPriorityBoost(sei.hProcess,TRUE);
// notify explorer shell of deletion
SHChangeNotify(SHCNE_DELETE,SHCNF_PATH,szModule,0);
return TRUE;
}
else
{
// otherwise, restore normal priority
SetPriorityClass(GetCurrentProcess(),NORMAL_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL);
}
}
return FALSE;
}