<?php

/*******************************************************************************

 WINBINDER - The native Windows binding for PHP for PHP

 Copyright © Hypervisual - see LICENSE.TXT for details
 Author: Rubem Pechansky (http://winbinder.org/contact.php)

 Creates a windowed PHP.EXE from the original executable (console)

*******************************************************************************/

//------------------------------------------------------------ SYSTEM PARAMETERS

define("PATH_SCRIPT",	dirname(__FILE__) . "/");
define("PATH_DATA",		PATH_SCRIPT);
define("PATH_INC",		PATH_SCRIPT . "../include/");
define("PATH_RES",		PATH_SCRIPT . "../resources/");

//----------------------------------------------------------------- DEPENDENCIES

include PATH_INC . "winbinder.php";

//-------------------------------------------------------------- USER PARAMETERS

define("APPNAME",			"Console to Windowed EXE converter");	// Application name

//-------------------------------------------------------------------- CONSTANTS

// Control identifiers

define("ID_OPEN",			102);
define("ID_CONVERT",		103);
define("ID_RESET",			104);
define("ID_HELP",			105);
define("ID_INSTRUCTIONS",	106);

// EXE file structures

define("DOSHEADER",
	"a2Id/" .
	"x22/" .
	"vWinHeader/" .
	"x34/" .
	"vTableOffset"
);
define("DOSHEADER_SIZE", 62);

define("WINHEADER",
	"a2Signature/" .
	"x18/" .
	"vNT32/" .
	"x70/" .
	"CConsole"
);
define("WINHEADER_SIZE", 93);

// Strings

define("INSTRUCTIONS",
APPNAME . "\n\n" .
"This is a small utility designed to suppress the console window from a PHP executable (PHP.EXE). It should be able to do the same with other console-mode executables, although only PHP executables were tested.\n\n" .
"This application works with PHP 4.3 and PHP 5.\n\n" .
"To create a pure windowed executable (no console window), use the Open button to select a PHP.EXE file. Then \n\n" .
"And then...");

//-------------------------------------------------------------- EXECUTABLE CODE

// Create main window

$mainwin = wb_create_window(NULL, PopupWindow, APPNAME, 320, 140);
wb_set_handler($mainwin, "process_main");

// Create menu, toolbar and controls

wb_create_control($mainwin, Menu, array(
	"&File",
		array(ID_OPEN,		"&Open...\tCtrl+O",		NULL, PATH_RES . "menu_open.bmp", "Ctrl+O"),
		array(ID_RESET,		"&Close...",			NULL),
		null,
		array(ID_CONVERT,	"&Convert...\tCtrl+S",	NULL, NULL, "Ctrl+S"),
		null,
		array(IDCLOSE,		"E&xit\tAlt+F4",		NULL, PATH_RES . "menu_exit.bmp"),
	"&Help",
		array(ID_HELP,		"Instructions...\tF1",	NULL, PATH_RES . "menu_help.bmp", "F1"),
));

$toolbar = wb_create_control($mainwin, ToolBar, array(
	null,
	array(ID_OPEN,		NULL,	"Open a PHP executable", 1),
	array(ID_CONVERT,	NULL,	"Convert it",	22),
	array(ID_RESET,		NULL,	"Close all",	12),
	null,
	array(ID_HELP,		NULL,	"Help",	13),
), 0, 0, 16, 15, 0, 0, PATH_RES . "toolbar.bmp");

wb_create_control($mainwin, Frame, "", 0, 28, 615, 3);
wb_create_control($mainwin, Label, "", 0, 49, 320, 40, ID_INSTRUCTIONS, WBC_CENTER);

reset_all();

// Enter application loop

wb_main_loop();

//-------------------------------------------------------------------- FUNCTIONS

/* Process main window commands */

function process_main($window, $id)
{
	global $filename, $toolbar;

	static $file_filter = array(
		array("PHP executables", "php*.exe"),
		array("All executables", "*.exe"),
		array("All files",       "*.*")
	);

	switch($id) {

		case ID_OPEN:
			$filename = wb_sys_dlg_open($window, "Select an executable file", $file_filter, wb_get_system_info("exepath"));
			if($filename) {
				$file = basename($filename);
				$mode = get_mode($filename);
				if($mode == NULL) {
					wb_message_box($window, "$file is not an executable file or has an invalid header.", APPNAME, WBC_INFO);
					break;
				}
				wb_set_text(wb_get_control($window, ID_INSTRUCTIONS),
				  "The file selected, $file, is a $mode\napplication. Now press Convert to create a new executable.");
				wb_set_enabled(wb_get_control($toolbar, ID_RESET), true);
				wb_set_enabled(wb_get_control($toolbar, ID_CONVERT), true);
			}
			break;

		case ID_RESET:
			if(wb_message_box($window, "Do you want to start over?", APPNAME, WBC_YESNO))
				reset_all();
			break;

		case ID_CONVERT:

			// Build name of new executable

			if(strstr($filename, "-win.exe")) {
				$newfile = str_replace("-win.exe", ".exe", $filename);
			} elseif(strstr($filename, "_win.exe")) {
				$newfile = str_replace("_win.exe", ".exe", $filename);
			} else {
				$newfile = str_replace(".exe", "-win.exe", $filename);
			}

			$file = basename($newfile);
			if(file_exists($newfile)) {
				if(!wb_message_box($window, "File $file already exists. Do you want to overwrite it?", APPNAME, WBC_YESNO))
					break;
			}
			if(@copy($filename, $newfile)) {
				convert($newfile);
				wb_set_text(wb_get_control($window, ID_INSTRUCTIONS), "Conversion complete. The new executable file\nwas saved as $file.");
			} else
				wb_message_box($window, "Error writing $file. ", APPNAME, WBC_WARNING);
			break;

		case ID_HELP:
			$dlg = wb_create_window(NULL, ModalDialog, APPNAME . " instructions", 480, 340);
			$list = wb_create_control($dlg, EditBox, INSTRUCTIONS, 0, 0, 475, 315, 101, WBC_MULTILINE | WBC_READONLY);
			wb_set_handler($dlg, "process_dlg");
			break;

		case IDCLOSE:
			wb_destroy_window($window);
			break;
	}
}

function process_dlg($window, $id)
{
	switch($id) {
		case IDCLOSE:
		case IDCANCEL:
			wb_destroy_window($window);
			break;
	}
}

function reset_all()
{
	global $mainwin, $toolbar, $filename;

	$filename = "";
	wb_set_text(wb_get_control($mainwin, ID_INSTRUCTIONS), "Use the Open button to select an executable file\n(Generally PHP.EXE or PHP-WIN.EXE).");
	wb_set_enabled(wb_get_control($toolbar, ID_RESET), false);
	wb_set_enabled(wb_get_control($toolbar, ID_CONVERT), false);
}

function convert($file)
{
	$fh = fopen($file, "rw+b");
	$doshead = unpack(DOSHEADER, fread($fh, DOSHEADER_SIZE));

	if($doshead["Id"] != "MZ" || $doshead["WinHeader"] < 0x40) {
		fclose($fh);
		return false;
	}

	fseek($fh, $doshead["TableOffset"], SEEK_SET);
	$winhead = unpack(WINHEADER, fread($fh, WINHEADER_SIZE));
	if($winhead["Signature"] != "PE") {
		fclose($fh);
		return false;
	}

	if($winhead["NT32"] != 0xE0) {
		fclose($fh);
		return false;
	}

	fseek($fh, $doshead["TableOffset"] + WINHEADER_SIZE - 1, SEEK_SET);

	if($winhead["Console"] == 3)
		fwrite($fh, "\02");
	elseif($winhead["Console"] == 2)
		fwrite($fh, "\03");
	else {
		fclose($fh);
		return false;
	}

	fclose($fh);
	return true;
}

function get_mode($file)
{
	$fh = fopen($file, "rb");
	$doshead = unpack(DOSHEADER, fread($fh, DOSHEADER_SIZE));

	if($doshead["Id"] != "MZ" || $doshead["WinHeader"] < 0x40) {
		fclose($fh);
		return false;
	}

	fseek($fh, $doshead["TableOffset"], SEEK_SET);
	$winhead = unpack(WINHEADER, fread($fh, WINHEADER_SIZE));
	if($winhead["Signature"] != "PE") {
		fclose($fh);
		return false;
	}

	if($winhead["NT32"] != 0xE0) {
		fclose($fh);
		return false;
	}

	fclose($fh);

	return ($winhead["Console"] == 3) ? "console" : "windowed";
}

//-------------------------------------------------------------------------- END

?>