28 November 2015

A Function creates a silent local variable

The documentation on Naked shows an optimized example of a windows-procedure callback. Interesting is the fact, that the example shows GB-code using a Procedure rather than a Function. The code shows how to pass a return value to the caller of WndProc.

Proc WndProc(hWnd As Handle, msg As Int, _
  wParam As Int, lParam As Int) Naked
  Local RetVal
  '... Code ...
  Asm mov eax, [RetVal]
EndProc

The example is misleading in the assumption that you need to use a Procedure rather than a Function!

The example merely shows how to use a local variable RetVal to return a value to the caller of the subroutine, which in this particular case is the Windows OS. The assembler instruction mov eax, [RetVal] copies the value to return from the local variable in the eax-register. Returning a 32-bit value through eax, and 64-bit values through eax and edx, is conform the Windows StdCall convention. The caller of the subroutine knows from this convention that any return value (32-bits) is placed in eax. The caller may examine the eax register and can respond accordingly.

A Function is easier and safer
Most of us won’t use a Procedure when creating a callback. Instead, we will use a Function so that the need for an explicit Asm command disappears. With Function the GB-compiler generates the code to return a value. Because the compiler takes into account the Function’s data type, it generates code to put values into the correct registers. Maybe, in case of returning a simple Long value, putting a value into the eax register isn’t very hard, but when it comes to other types, like floating-point values or even Currency values, everything becomes more complicated.
For these reasons you will always turn to the use of Functions, you do not want to fiddle around with assembler instructions just to return some value.

Procedure and Function are not so different
On a pure theoretical level something interesting can be deduced. When a Function and a Procedure-returning-a-value are compared they actually are quite the same. For a Function the compiler silently inserts a local variable of the function’s data type and name. To return a value the Return value (or Exit Func) statement copies the value into the local variable - before it copies the value to the proper register(s). The function behaves the same as a procedure with an explicit local variable.
Consequently, a Function and a Procedure-returning-a-value are equally efficient, also when Naked is used. Both need a local variable to temporarily save a return value, which is later copied to the appropriate register(s). On the other hand the Procedure type doesn’t need a local variable to store a return value. Everything can be handled by registers using assembler. When using Naked the Sub or Procedure type can be used to create highly optimized code using assembler.

Function and Naked
When performance is a concern (hardly these days so it seems), you should realize that the compiler always silently inserts a local variable when it compiles a Function statement, even when the function doesn’t declare local variables it self. The compiler generates VB-compatible code for a Function and VB uses a local variable to return a value from a function. This leads to a small decrease in performance, because he compiler has to set up prologue and epilogue code for the Function. Naked has does not omit prologue and epilogue code generation, because of the use of a silent, hidden silent local variable to be stored in the stack.

When a Sub or Procedure doesn’t use local variables and parameters Naked optimizes by omitting prologue and epilogue code. For optimization reasons it might be useful to use a Naked Procedure and return a value using assembler. A Procedure does not add an additional local variable and lends itself better for using assembler or for creating optimized code.

Closing a child process

This is part 3 of a series on launching a Win32 application from GFA-BASIC 32. In the first part I discussed the WinExec based GB32 functions WinExec and Exec. Another WinExec based command is the Shell command spawning COMMAND.COM and is used to execute MSDOS commands, mainly. All WinExec based commands do not return any value identifying the application. The return value of WinExec based processes is not a handle of process ID and the child process is not accessible through program code.

The second part discusses the System command, which does provide meaningful return values. When used as a function, System() returns an Int64 value containing the process-handle and the process ID; the values by which a process is identified. The System command returns these values in explicitly provided by-reference variables. Both values can be used subsequent API functions, from which some accept a process handle and others a process ID.

One of these functions that accepts a process handle is TerminateProcess, which forces a process to exit. Actually this command brings the process to an abrupt and crashing halt, preventing some of the usual cleanup from happening. DLLs, for example, are not notified when TerminateProcess kills one of their clients. Like TerminateThread, TerminateProcess is abrupt, messy, and best avoided whenever possible or to be used as a last resort. We’ll see when and how to use in the code below that provides a GB function to cleanly close a spawned process.

Most documentation emphasizes to let the process come to a natural end. This means that the user quits the application as any other process. When synchronization is important – the application has to wait for the child process to terminate – specify the Wait keyword with the System command. GB32 makes sure the to wait for the child process to end while keeping the user-interface responsive. See the Help file for more details.

But what if you want to close the Win32 child process from your GB program? There is no command and there is also no Windows API function to accomplish this magic. However, there is a documented https://support.microsoft.com/en-us/kb/178893 that provides the solution when you have a process ID or handle. Here is the code translated to GFA-BASIC 32.

Global Const WAIT_OBJECT_0  = 0
Global Const PROCESS_TERMINATE  = 1

OpenW 1
Dim Process As Large
Process = System("Notepad.exe")
Dim hProcess As Long  = LoLarge(Process)
Dim ProcessID As Long = HiLarge(Process)

Do
  Sleep
Until Me Is Nothing

' Close nicely or terminate abruptly
CloseApp32(ProcessID, True)
' When System return processs handle
~CloseHandle(hProcess)

Function CloseApp32(pID%, Optional Force? = False) As Bool
  ' Purpose: (Forced) Shutdown a 32-Bit Process by PID
  ' Return : True success, False (0) failure
  ' See    : https:'support.microsoft.com/en-us/kb/178893

  Local Const TimeOut = 1000 'ms
  Local Handle hProc
  ' Get process handle when termination allowed
  hProc = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, 0,  pID)
  If hProc
    ' Post WM_CLOSE to all windows whose ProcessID == pID
    ~EnumWindows(ProcAddr(CloseApp32Enum), pID)
    ' Give process a moment to release all resources
    If WaitForSingleObject(hProc, TimeOut) == WAIT_OBJECT_0
      CloseApp32 = True  ' Return Succes
    ElseIf Force?        ' Kill it the messy way?
      CloseApp32 = TerminateProcess(hProc, 0)
    EndIf
    ~CloseHandle(hProc)
  EndIf
EndFunc

Function CloseApp32Enum(hwnd As Handle, lParam As Long) As Long Naked
  Local pID As Long
  ~GetWindowThreadProcessId(hwnd, V:pID)
  If pID == lParam _
    PostMessage hwnd, WM_CLOSE, 0, 0
  Return 1
EndFunc

The CloseApp32 function terminates an autonomously running 32-bits application by posting a WM_CLOSE to all the windows owned by the process. The window procedures of the detached application need to destroy resources that may take some time to complete. When the main thread has come to an end, all DLLs and other system resources are released. This also takes time. Therefore the function waits for at most 1000 ms to check if the process has ended. With many running applications the timeout value may be too short.

One other note. If the System function return a process handle the calling application is still responsible for closing it.

22 November 2015

Execute a new process using System

In a previous blog post Execute a new detached process I discussed GB32 commands to start a new detached program, or process. After the new process is created and executing, the parent process cannot communicate with the new process. There is no relationship between the both, hence the term detached. The GB32 commands WinExec, Exec rely on the WinExec() API, which does not return a process instance handle. The only thing you can get from WinExec is some error code when starting the new process somehow failed.

But there is System
Starting a new process might involve more than simply executing it and leaving it out there to be managed by the user. Maybe your program needs to wait for the second application to quit, or you want to execute a process with elevated privileges, or maybe you just want a handle on the new process so you can manage it programmatically. All of this can be done using System, command or function, depending on your needs.

The System command/function comes in two flavors. A simple version, a function, that only takes one parameter. Then there is the less simple one, implemented also as a command and function, taking multiple arguments. When you only need the creation of new process, for example to get a handle on it, use the simple version. It only takes one parameter, the command line. The command line is a null-terminated character string that contains the filename plus optional parameters:

Large = System("filename [parameters]")

This looks much like the WinExec() – and Exec()  – function, but without the the show-window  argument (which is most of the times a ShowWindow SW_* constant to make the new process visible). The difference between System and the other functions is the meaningful return value, a 64-bit integer holding the process-handle and its process identification number. Together these values uniquely identify the new process.

Using System requires some effort
Using the System() function comes with a responsibility. The process handle must be freed using the CloseHandle(hProcess) API.  First let’s see how to use System() and how to interpret the return value:

Global Int32 hProcess   ' keep in memory
Local Int32 ProcessId   ' you may keep it
Local Large Process64   ' can be discarded
Exe$ = "process.exe", Param$ = "-options"

Process64 = System(Exe$ & " " & Param$)
hProcess  = LoLarge(Process64)
ProcessId = HiLarge(Process64)

In this scenario the System() function replaces WinExec, and Exec (and maybe ShellExec but that is a different story).

It might be preferable, because System() invokes the CreateProcess API directly, passing it Null for all parameters, except for the lpszCmdLine argument and the argument taking if the address of a PROCESS_INFORMATION structure. This structure receives the output (or return values) of CreateProcess. It is used to store/return four values; the process an thread handles, and the process-id and the thread-id. GB32 only returns the process handle and process-id through an Int64 data-type.

Taking a closer look at those handles
In pseudo GB32 code, System(cmdline$) function acts like this:

Dim pi As PROCESS_INFORMATION
If CreateProcess(0,cmdline$,0,…, V:pi)
~CloseHandle(pi.hTread)
Return MakeLarge(pi.Process.Id, pi.hProcess)
EndIf

Generally, CloseHandle API only decrements a reference count on a handle. When the reference count reaches zero, the OS knows that the object can be freed. That’s all, it is not some kind of destroy-function. Closing a handle might become your responsibility, keep these rules in mind:

  • With the function variant of System(), GB32 only closes the handle to the primary thread. It returns the process handle and you have to close it in time.
  • With the System command both handles are automatically closed - unless you explicitly ask for them as return values.

When you specify the “hProcess var” and/or “hThread var” options with the System command you are explicitly asking to obtain the handles and taking responsibility. For instance, in the following code System does not call CloseHandle on the handles:

Global Handle hProcess
System FileName$, hProcess hProcess, hThread hThread

When, one way or the other, the program gains ownership of a handle, it is also responsible for closing it. The application should close a handle when it isn’t necessary anymore. A good place for a call to CloseHandle could be in your exit code, after the main message loop in the main section of your program:

Do
  Sleep
Until Me Is Nothing
~CloseHandle(hProcess)
' End of Program

Termination and usage count
CreateProcess creates two objects identified using handles: a handle to a thread object and a handle to a process object. These objects are given an initial usage count of one. Then, just before CreateProcess returns, the function opens both the process and the thread object and increments the usage count again to two. It then places handles and IDs in the members of the PROCESS_INFORMATION structure. In the end, CreateProcess has set the usage count for both objects to two. In the end, the handles must be decremented twice to reach zero.

Before the OS can completely free the process, it must - of course – terminate. This will decrement the usage count with one to one. To reach a zero usage count, the parent process must also call CloseHandle. Only then the final usage count od zero is reached. 
To free the primary thread object, a two step decrement is also required. The thread’s usage count is decremented when its process terminates. (During process termination the thread’s handle is closed). But this leaves the thread with a count of one. Because the System command already decremented the usage count of the thread, it can be freed as well.

The reason to immediately close the primary thread’s handle must be found in the OS. It has something to do with multiple creations of the same process. I don’t know why, but it is heavily recommended to proceed this way. The process handle on the other hand can be kept to be used in future API calls that require a process-handle.

In the next post I’ll discuss the termination of child process.

17 November 2015

Execute a new detached process

What if you want to execute another program (process) from a GFA-BASIC 32 program? GB32 offers quite some commands and functions to do so. However, every new process is eventually started by calling the CreateProcess() API function. All those functions, including Windows API functions like ShellExecute(), WinExec() invoke the CreateProcess() API, which is declared as follows:

BOOL CreateProcess(
   LPCTSTR lpszImageName,              // image file (.EXE) name
   LPCTSTR lpszCmdLine,                // command line for new process
   LPSECURITY_ATTRIBUTES lpsaProcess,  // how process will be shared
   LPSECURITY_ATTRIBUTES lpsaThread,   // how new thread will be shared
   BOOL bInheritHandles,               // TRUE to inherit handles
   DWORD fdwCreate,                    // creation flags
   LPVOID lpvEnvironment,              // new environment (default = NULL)
   LPTSTR lpszCurrentDir,              // name of new current directory
   LPSTARTUPINFO lpStartupInfo,        // gives info about new process
   LPPROCESS_INFORMATION lpProcInfo )  // receives info about new process

WinExec - Command and Function
The CreateProcess function’s parameters permit precise control over the new process’s starting conditions. Because of these big number of parameters and options, some commands provide a simplified execution of CreateProcess. The WinExec() API already invokes CreateProcess with a lot of default values to create a detached process. WinExec() only expects lpszCmdLine and a show-window value for the STARTUPINFO.dwFlags member. All other values are set to zero or other default values. The new process is not a child process; after it is started there is no elation between the parent and the child process whatsoever.
WinExec() is a GB32 built-in API function, but it is not used. Instead GB32 uses its own WinExec function and it is defined as:

[Long =] WinExec(CmdLine$, CmdShow%)             

The CmdLine$ is a null-terminated character string that contains the command line (file name plus optional parameters) for the application to be executed. WinExec passes parameters to the CreateProcess function in such a way that it is compatible to the 16-bits version of Windows. The return value is greater than 31 if the function succeeds. Otherwise it returns an error value

Value Meaning
0 The system is out of memory or resources.
ERROR_BAD_FORMAT (1) The .exe file is invalid.
ERROR_FILE_NOT_FOUND (2) The specified file was not found.
ERROR_PATH_NOT_FOUND(3) The specified path was not found.

The 32-bit WinExec() does not return an instance handle as the 16-bit WinExec() does. The return value can only be used to inspect an error value. Therefore, GB32 also defines a command variant: WinExec CmdLine$, CmdShow%.
Both versions - function and command - are linked to the same runtime function. Obviously, the return value can only be obtained with the function variant.

Exec – Command and Function
The WinExec takes two parameters, a command line argument and a show-window argument. Most of the times the second argument will be a default value of SW_SHOW or SW_SHOWNORMAL. The GB32 command Exec takes advantage of this behavior and allows the command-line parameter CmdLine$ to be split into a filename (path included) and options part. Although this might be useful for the developer, the command itself concatenates the parts before WinExec() API is invoked. The SW_SHOW is automatically used.

[Long =] Exec(file$, parameters$)   

ShellExec – Command and Function
All processes are started using CreateProcess. It depends on the function which parameters are set and to what value. The GB32 ShellExec command/function invokes the ShellExecute() API, which sets and fills another set of CreateProcess’ arguments. Where the Exec and WinExec commands allow a simple start of a named exe program, the ShellExecute() function allows to start a process by a registered extension. Depending on the version used, ShellExec allows a more extended set of parameters for CreateProcess. In itself is ShellExec also a simplified form of invoking CreateProcess. See the help for more information on the parameters that can be used. For a comparison with WinExec and Exec we’ll only look at the variant that takes two parameters and performs exactly like these GB32 functions:

[Long = ] ShellExec file$ [, parameters$]

It doesn’t matter which GB32 command/function you use to spawn a new detached process. They all invoke the CreateProcess API. The return values of the function do not provide some handle to the new process, only an error value (if less than 32). Using Exec is tempting because it provides the easiest interface where the file and parameters are split.

GFA-BASIC 32 does provide a function that bypasses the above mentioned shortcuts to CreateProcess(): the System function/command. I will discuss this briefly in a next post.