This tool is primarily aimed at folks who own either of the PB compilers but not both. Run it on any 32 bit PE executable file and it will toggle between subsystem WINDOWS and subsystem CONSOLE. It is done the right way using the MZ (DOS) header and the PE (NT) header.
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
' Build with PBCC 6
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
#compile exe "setsubsys.exe"
#include "\basic\include\win32api.inc"
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION PBmain as LONG
LOCAL pFile as DWORD
cmd$ = command$
pefile$ = load_file(cmd$)
pFile = StrPtr(pefile$)
set_pe pFile
save_file(cmd$,pefile$)
End FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION set_pe(ByVal pFile as DWORD) as DWORD
LOCAL va as DWORD
dim doshdr(0) as IMAGE_DOS_HEADER at pFile ' load the MZ (DOS) header
va = pFile + doshdr(0).e_lfanew ' get the OFFSET of the PE (NT) header
dim nt_hdr(0) as IMAGE_NT_HEADERS at va ' load the PE (NT) header
' -------------------------
' toggle between subsystems
' -------------------------
If (nt_hdr(0).OptionalHeader.Subsystem) = 2 Then
nt_hdr(0).OptionalHeader.Subsystem = 3
conout "Subsystem set to CONSOLE"
Else
nt_hdr(0).OptionalHeader.Subsystem = 2
conout "Subsystem set to WINDOWS"
End If
erase doshdr()
erase nt_hdr()
End FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
DECLARE FUNCTION open_file_A LIB "KERNEL32.DLL" ALIAS "CreateFileA" ( _
ByVal lpFileName AS DWORD, _
ByVal dwDesiredAccess AS DWORD, _
ByVal dwShareMode AS DWORD, _
ByVal lpSecurityAttributes AS DWORD, _
ByVal dwCreationDisposition AS DWORD, _
ByVal dwFlagsAndAttributes AS DWORD, _
BYVAL hTemplateFile AS DWORD) AS DWORD
DECLARE FUNCTION get_file_size LIB "KERNEL32.DLL" ALIAS "GetFileSize" ( _
BYVAL hFile AS DWORD, lpFileSizeHigh AS LONG) AS LONG
DECLARE FUNCTION file__read LIB "KERNEL32.DLL" ALIAS "ReadFile" ( _
BYVAL hFile AS DWORD,ByVal pbuff as DWORD, BYVAL nNumberOfBytesToRead AS DWORD, _
ByVal lpNumberOfBytesRead AS DWORD, ByVal lpOverlapped AS DWORD) AS LONG
DECLARE FUNCTION closefh LIB "KERNEL32.DLL" ALIAS "CloseHandle" ( _
BYVAL hObject AS DWORD) AS LONG
' ------------------------------------
FUNCTION load_file(fname$) as STRING
LOCAL hFile as DWORD
LOCAL flen as DWORD
LOCAL pdat as DWORD ' string pointer
LOCAL bred as DWORD ' bytes read variable
hFile = open_file_A(StrPtr(fname$),&H80000000& or &H40000000&,0,0,3,&H00000080,0)
flen = get_file_size(hFile,0)
buffer$ = nul$(flen)
pdat = StrPtr(buffer$)
file__read(hFile,pdat,flen,VarPtr(bred),0)
closefh hFile
FUNCTION = buffer$
End FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
DECLARE FUNCTION fcreate_A LIB "KERNEL32.DLL" ALIAS "CreateFileA" ( _
ByVal lpFileName AS DWORD, _
ByVal dwDesiredAccess AS DWORD, _
ByVal dwShareMode AS DWORD, _
ByVal lpSecurityAttributes AS DWORD, _
ByVal dwCreationDisposition AS DWORD, _
ByVal dwFlagsAndAttributes AS DWORD, _
BYVAL hTemplateFile AS DWORD) AS DWORD
DECLARE FUNCTION file__write LIB "KERNEL32.DLL" ALIAS "WriteFile" ( _
BYVAL hFile AS DWORD,ByVal lpBuffer AS DWORD, _
BYVAL nNumberOfBytesToWrite AS DWORD, _
ByVal NumberOfBytesWritten AS DWORD,ByVal lpOverlapped AS DWORD) AS DWORD
DECLARE FUNCTION fh_close LIB "KERNEL32.DLL" ALIAS "CloseHandle" ( _
BYVAL hObject AS DWORD) AS LONG
' ------------------------------------------
FUNCTION save_file(fname$,src$) as DWORD
LOCAL hFile as DWORD
LOCAL pdat as DWORD ' string pointer
LOCAl ldat as DWORD ' data length
LOCAL bwrt as DWORD ' bytes written variable
hFile = fcreate_A(StrPtr(fname$),&H40000000&,0,0,2,&H00000080,0)
pdat = StrPtr(src$) ' get string address
! mov eax, pdat
! mov eax, [eax-4] ' get string length
! mov ldat, eax
file__write(hFile,pdat,ldat,VarPtr(bwrt),0)
fh_close hFile
FUNCTION = bwrt
End FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
DECLARE FUNCTION CO_GetStdHandle LIB "KERNEL32.DLL" ALIAS "GetStdHandle" (BYVAL nStdHandle AS DWORD) AS DWORD
DECLARE FUNCTION CO_WriteFile LIB "KERNEL32.DLL" ALIAS "WriteFile" (BYVAL hFile AS DWORD, _
ByVal lpBuffer AS DWORD, BYVAL nNumberOfBytesToWrite AS DWORD, _
ByVal lpNumberOfBytesWritten AS DWORD, ByVal lpOverlapped AS DWORD) AS LONG
MACRO CO_STD_OUTPUT_HANDLE = -11&
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION conout(txt$,OPT ByVal arg as DWORD) as DWORD
' -------------------------------------------
' conout basic$ = default appends CRLF
' conout basic$, 0 = default appends CRLF
' conout basic$, 1 = non zero omits CRLF
' bytes_written = conout(basic$,[opt arg])
' -------------------------------------------
#REGISTER NONE
LOCAL hOutPut as DWORD
LOCAL bWritten as DWORD
LOCAL slen as DWORD
LOCAL ptxt as DWORD
If arg = 0 Then
txt$ = txt$ + $CRLF
End if
ptxt = StrPtr(txt$)
PREFIX "! "
mov eax, ptxt ; load address into EAX
mov eax, [eax-4] ; get length store 4 bytes below
mov slen, eax ; write it to a variable
END PREFIX
hOutPut = CO_GetStdHandle(CO_STD_OUTPUT_HANDLE)
CO_WriteFile hOutPut,ptxt,slen,VarPtr(bWritten),0
FUNCTION = bWritten
END FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤