
// Quick & dirty hack by Firesledge

#include	<cstdio>
#include	<Windows.h>
#include <tlhelp32.h>


// Code from http://www.codeproject.com/Articles/9893/Get-Parent-Process-PID
BOOL GetParentPID( PROCESSENTRY32& procentry )
{
	OSVERSIONINFO  osver ;
	HINSTANCE      hInstLib ;
	HANDLE         hSnapShot ;
	BOOL           bContinue ;

	// ToolHelp Function Pointers.
	HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
	BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
	BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;

	// Check to see if were running under Windows95 or
	// Windows NT.
	osver.dwOSVersionInfoSize = sizeof( osver ) ;
	if( !GetVersionEx( &osver ) )
	{
		return FALSE ;
	}

	if( osver.dwPlatformId != VER_PLATFORM_WIN32_NT )
	{
		return FALSE;
	}

	hInstLib = LoadLibraryA( "Kernel32.DLL" ) ;
	if( hInstLib == NULL )
	{
		return FALSE ;
	}

	// Get procedure addresses.
	// We are linking to these functions of Kernel32
	// explicitly, because otherwise a module using
	// this code would fail to load under Windows NT,
	// which does not have the Toolhelp32
	// functions in the Kernel 32.
	lpfCreateToolhelp32Snapshot=
		(HANDLE(WINAPI *)(DWORD,DWORD))
		GetProcAddress( hInstLib,
		"CreateToolhelp32Snapshot" ) ;
	lpfProcess32First=
		(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
		GetProcAddress( hInstLib, "Process32First" ) ;
	lpfProcess32Next=
		(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
		GetProcAddress( hInstLib, "Process32Next" ) ;
	if( lpfProcess32Next == NULL ||
	    lpfProcess32First == NULL ||
	    lpfCreateToolhelp32Snapshot == NULL )
	{
		FreeLibrary( hInstLib ) ;
		return FALSE ;
	}

	// Get a handle to a Toolhelp snapshot of the systems
	// processes.
	hSnapShot = lpfCreateToolhelp32Snapshot(
	TH32CS_SNAPPROCESS, 0 ) ;
	if( hSnapShot == INVALID_HANDLE_VALUE )
	{
		FreeLibrary( hInstLib ) ;
		return FALSE ;
	}

	// Get the first process' information.
	memset((LPVOID)&procentry,0,sizeof(PROCESSENTRY32));
	procentry.dwSize = sizeof(PROCESSENTRY32) ;
	bContinue = lpfProcess32First( hSnapShot, &procentry ) ;
	DWORD pid = 0;
	// While there are processes, keep looping.
	DWORD  crtpid= GetCurrentProcessId();
	while( bContinue )
	{
		if(crtpid == procentry.th32ProcessID)
		{
			pid =  procentry.th32ParentProcessID;
		}
			
		procentry.dwSize = sizeof(PROCESSENTRY32) ;
		bContinue = !pid && lpfProcess32Next( hSnapShot, &procentry );

	}//while ends


	// Free the library.
	FreeLibrary( hInstLib ) ;

	return pid?TRUE:FALSE ;
}

// Disables the deprecated function warning
#pragma warning (push)
#pragma warning (4 : 4996)

int main (int argc, char *argv [])
{
	if (argc != 2)
	{
		printf ("Error. Usage:\nsetbatpriority [low | belownormal | normal | abovenormal | high | realtime]\n");
		return (1);
	}

	int            prio = NORMAL_PRIORITY_CLASS;
	if (     stricmp (argv [1], "low"        ) == 0) { prio = IDLE_PRIORITY_CLASS;         }
	else if (stricmp (argv [1], "belownormal") == 0) { prio = BELOW_NORMAL_PRIORITY_CLASS; }
	else if (stricmp (argv [1], "normal"     ) == 0) { prio = NORMAL_PRIORITY_CLASS;       }
	else if (stricmp (argv [1], "abovenormal") == 0) { prio = ABOVE_NORMAL_PRIORITY_CLASS; }
	else if (stricmp (argv [1], "high"       ) == 0) { prio = HIGH_PRIORITY_CLASS;         }
	else if (stricmp (argv [1], "realtime"   ) == 0) { prio = REALTIME_PRIORITY_CLASS;     }
	else
	{
		printf ("Error: unknown process priority for setbatpriority.\n");
		return (1);
	}

	::PROCESSENTRY32 procentry;
	if (! GetParentPID (procentry))
	{
		printf ("Error: setbatpriority cannot get the parent PID.\n");
		return (1);
	}
	
//	printf ("%d\n", procentry.th32ParentProcessID);

	::HANDLE       hnd = ::OpenProcess (PROCESS_SET_INFORMATION, 0, procentry.th32ParentProcessID); 
	if (hnd == 0)
	{
		printf ("Error: setbatpriority cannot open the parent process.\n");
		return (1);
	}
	const ::BOOL   succ = ::SetPriorityClass (hnd, prio);
	::CloseHandle (hnd);
	if (! succ)
	{
		printf ("Error: setbatpriority cannot change the parent process priority.\n");
		return (1);
	}
	
	return (0);
}

#pragma warning (pop)
