The Application Mode Changer

'Application Mode Changer
'Copyright (c) 2002 Nir Sofer
'
'Web site: http://nirsoft.mirrorz.com
'
'This small utility allows you to change the mode of an executable file (.exe) from
'GUI mode to console mode and vise versa.
'You can use this utility for creating console applications in Visual Basic environment.
'
'In order to do this, follow the instructions below:
'1. Write a console application in Visual Basic by using API calls (You can learn how to do it from my sample project)
'2. Create an executable file from your VB project.
'3. Run this utility, select your executable file, and click the "Change Mode" button. Your executable will be switched from GUI mode to console mode.
'
'If you successfully do the above 3 steps, you'll get a real console application !

Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Const INVALID_HANDLE_VALUE = -1
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const OPEN_EXISTING = 3

Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Const FILE_BEGIN = 0

'Application Modes:
Private Const IMAGE_SUBSYSTEM_WINDOWS_GUI = 2    'GUI Application
Private Const IMAGE_SUBSYSTEM_WINDOWS_CUI = 3    'Console Application

Private Const ERROR_CANNOT_WRITE_FILE = 1
Private Const ERROR_BAD_FILE_FORMAT = 2
Private Const ERROR_CANNOT_READ_FILE = 3
Private Const ERROR_CANNOT_OPEN_FILE = 4


Private Function GetErrorDesc(iError As Integer) As String
    Select Case iError
        Case ERROR_CANNOT_WRITE_FILE
            GetErrorDesc = "Cannot write to the file"
        
        Case ERROR_BAD_FILE_FORMAT
            GetErrorDesc = "Bad file format"
        
        Case ERROR_CANNOT_READ_FILE
            GetErrorDesc = "Cannot read from the file"
        
        Case ERROR_CANNOT_OPEN_FILE
            GetErrorDesc = "Cannot open the file"
    End Select
End Function

Private Sub ChangeMode(sFilename As String, iAppMode As Integer)
    Dim hFile           As Long
    Dim iError          As Integer
    Dim buffer(1024)    As Byte
    Dim lBytesReadWrite As Long
    Dim lPELocation     As Long
    
    'Open the file with Win32 API call
    hFile = CreateFile(sFilename, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
    If hFile <> INVALID_HANDLE_VALUE Then
        'Read the Dos header.
        If ReadFile(hFile, buffer(0), &H40, lBytesReadWrite, 0) <> 0 Then
            If buffer(0) = &H4D And buffer(1) = &H5A Then
                'Get the location of the portable executable header.
                CopyMemory lPELocation, buffer(&H3C), 4
                If lPELocation = 0 Then
                    iError = ERROR_BAD_FILE_FORMAT
                Else
                    SetFilePointer hFile, lPELocation, ByVal 0, FILE_BEGIN
                    'Read the portable executable signature.
                    If ReadFile(hFile, buffer(0), 2, lBytesReadWrite, 0) <> 0 Then
                        'Check the signature.
                        If buffer(0) = &H50 And buffer(1) = &H45 Then
                            buffer(0) = iAppMode
                            SetFilePointer hFile, lPELocation + &H5C, ByVal 0, FILE_BEGIN
                            'Change the byte in the executable file to the desired application mode.
                            If WriteFile(hFile, buffer(0), 1, lBytesReadWrite, 0) = 0 Then
                                iError = ERROR_CANNOT_WRITE_FILE
                            End If
                            
                        Else
                            iError = ERROR_BAD_FILE_FORMAT
                        End If
                    Else
                        iError = ERROR_CANNOT_READ_FILE
                    End If
                End If
                
            Else
                iError = ERROR_BAD_FILE_FORMAT
            End If
        Else
            iError = ERROR_CANNOT_READ_FILE
        End If
                
        'Close the file
        CloseHandle hFile
    Else
        iError = ERROR_CANNOT_OPEN_FILE
    End If
    
    If iError = 0 Then
        MsgBox "The application mode was successfully changed", vbOKOnly Or vbInformation, ""
    Else
        MsgBox "Error: " & GetErrorDesc(iError), vbOKOnly Or vbExclamation, "Error"
    End If
End Sub

Private Sub cmdBrowse_Click()
    On Error GoTo canceled
    'Show the open dialog.
    OpenDialog.Flags = cdlOFNExplorer Or cdlOFNFileMustExist Or cdlOFNHideReadOnly
    OpenDialog.ShowOpen
    txtFilename.Text = OpenDialog.FileName
    Exit Sub
canceled:

End Sub

Private Sub cmdChange_Click()
    ChangeMode txtFilename.Text, IIf(ModeOption(1).Value, IMAGE_SUBSYSTEM_WINDOWS_GUI, IMAGE_SUBSYSTEM_WINDOWS_CUI)
End Sub


Return back to the main console application page