Secure Sockets Layer


Hello Guest
Did you know this forum has been running since 2010?


Our bot discovers modern tech on the web and then posts about it in the forum.

Recent Topics

Stop Burning Stuff


Can You Help?

Help keep our site running
Advert free.

Web Utilities

Linux cross compiles Windows applications

Started by, March 29, 2016, 02:34:17 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic. Total views: 4,578

Linux, believe it or not, compiles Microsoft Windows graphical user interface (GUI) applications.
And, Linux executes these Microsoft Windows applications under WINE once they are complied.
This is what is known as cross compiling, which is the topic of this discussion thread.
My Very Enormous Monster Just Stopped Using Nine

Cross Compiler

Simple Windows program, written in C Language and the Win32 API.  Compiled on Linux.  
Running under WINE in Linux.  Notice the little WINE icon (top, left corner)?  

#include <windows.h>
int main(int argc, char *argv[])
return 0;

Not to be confused a Linux program, this program will run on a Windows machine.

My Very Enormous Monster Just Stopped Using Nine


Interesting. But the WIN32 API has been available to *nix platforms for several years now. I'm waiting for the day that modern Windows apps can be compiled to run in WINE's successor, but I don't see that happening any time soon. :)
Safe, Reliable Insanity, Since 1961!

Hi Dave,

Correct me if I am wrong, but any Windows computer with less than a Core 2 Duo is Win32.
It won't use the full 64bit registers, but it's still plenty good enough.  I wonder if it is still true
that more things run on 32bit than 64bit?

I'm investigating rolling back from .NET C# to Win32 C Language, to build an entry for the
Loebner Prize Contest.  This is not a perfect demonstration, but it shows how source code
found on the web, may be compiled with a cross compiler.

  Credit to: Log Window Test App - by Napalm
  You may use all or any part of the following code as long as you agree
  to the Creative Commons Attribution 2.0 UK: England & Wales license.

  Original source code modified 4/1/16 to simplify a demonstration of how
  Windows source code may be cross compiled on Linux, to run on Windows.  

#include <windows.h>
#include <shlwapi.h>
// Child Window/Control IDs
#define IDC_TXTENTRY            100
#define IDC_TXTLOG              101
#define IDC_BTNADDENTRY         102

// Globals
HFONT g_hfText;

// I created this to change the default properties of how edit controls behave
// when accessed by the dialog manager.
LRESULT CALLBACK SubclassEditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
   WNDPROC wpOld = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_USERDATA);
   LRESULT lrResult = 0;

           // Last message to a window so we de-subclass ourselves.
           case WM_NCDESTROY:
               SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)wpOld);
               SetWindowLongPtr(hWnd, GWLP_USERDATA, 0);

           // Sent by IsDialogMessage() API to determine what keys the control wants.
           // We use this to forward the tab key so it selects the next control.
           case WM_GETDLGCODE:
               lrResult = CallWindowProc(wpOld, hWnd, uMsg, wParam, lParam);
               lrResult &= ~(DLGC_HASSETSEL | DLGC_WANTTAB);
               if(lParam && ((LPMSG)lParam)->message == WM_KEYDOWN &&
                   ((LPMSG)lParam)->wParam == VK_TAB)
                   lrResult &= ~DLGC_WANTMESSAGE;
               return lrResult;

       // Call the original window procedure.
       return CallWindowProc(wpOld, hWnd, uMsg, wParam, lParam);

   // Crap couldn't find the original window procedure... use default.
   return DefWindowProc(hWnd, uMsg, wParam, lParam);

   // We should not have used a static.. we should really attach this value to the window
   // using either GWL_USERDATA or a allocated structure with a a pointer stored in GWL_USERDATA.
   static HWND s_hWndLastFocus;

       // Initialize our window and create our child controls.
       case WM_CREATE:
               HWND hWndChild;
               TCHAR szBuffer[MAX_PATH];

               hWndChild = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, NULL,
                   0, 0, 0, 0, hWnd, (HMENU)IDC_TXTENTRY, g_hInst, NULL);
               if(!hWndChild) return -1;
               // Subclass the edit control.
               SetWindowLongPtr(hWndChild, GWLP_USERDATA, GetWindowLongPtr(hWndChild, GWLP_WNDPROC));
               SetWindowLongPtr(hWndChild, GWLP_WNDPROC, (LONG_PTR)SubclassEditProc);
               // Set the edit controls properties.
               SendMessage(hWndChild, WM_SETFONT, (WPARAM)g_hfText, FALSE);
               SendMessage(hWndChild, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, 0);

               s_hWndLastFocus = NULL;

               // Create a 'Chat' button.
               hWndChild = CreateWindowEx(0, WC_BUTTON, TEXT("&Chat"),
                   BS_PUSHBUTTON | BS_TEXT |
                   WS_CHILD | WS_TABSTOP | WS_VISIBLE,
                   0, 0, 0, 0, hWnd, (HMENU)IDC_BTNADDENTRY, g_hInst, NULL);
               if(!hWndChild) return -1;
               // Set the button controls properties.
               SendMessage(hWndChild, WM_SETFONT, (WPARAM)g_hfText, FALSE);

               // Create 'log window' multi-line edit control.
               hWndChild = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, NULL,
                   0, 0, 0, 0, hWnd, (HMENU)IDC_TXTLOG, g_hInst, NULL);
               if(!hWndChild) return -1;
               // Subclass the edit control.
               SetWindowLongPtr(hWndChild, GWLP_USERDATA, GetWindowLongPtr(hWndChild, GWLP_WNDPROC));
               SetWindowLongPtr(hWndChild, GWLP_WNDPROC, (LONG_PTR)SubclassEditProc);
               // Set the edit controls properties.
               SendMessage(hWndChild, WM_SETFONT, (WPARAM)g_hfText, FALSE);
               SendMessage(hWndChild, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, 0);                
           return 0;

       // We get this message with WA_INACTIVE set when our window is no-longer
       // the foreground window so we want to save which of our controls has the focus
       // so that when the user returns the right control gets the keyboard input.
       case WM_ACTIVATE:
           if(LOWORD(wParam) == WA_INACTIVE)
               s_hWndLastFocus = GetFocus();
           return 0;

       // We get this message when our window receives the user focus. We then
       // move that focus to the previously used child window.
       case WM_SETFOCUS:
           return 0;

       // We accept this message so we can set a minimum window size. This only sets the users
       // tracking size. The window itself can always be resized smaller programmatically unless
               LPMINMAXINFO lpInfo = (LPMINMAXINFO)lParam;
                   lpInfo->ptMinTrackSize.x = 350, lpInfo->ptMinTrackSize.y = 280;
           return 0;

       // These next two messages are better to use rather than WM_MOVE/WM_SIZE.
       // Remember WM_MOVE/WM_SIZE are from 16bit windows. In 32bit windows the window
       // manager only sends these two messages and the DefWindowProc() handler actually
       // accepts them and converts them to WM_MOVE/WM_SIZE.
       // We accept this so we can scale our controls to the client size.
               HDWP hDWP;
               RECT rc;

               // Create a deferred window handle.
               if(hDWP = BeginDeferWindowPos(5)){ // Deferring 5 child controls
                   GetClientRect(hWnd, &rc);

                   // Defer each window move/size until end and do them all at once.
                   hDWP = DeferWindowPos(hDWP, GetDlgItem(hWnd, IDC_TXTENTRY), NULL,
                       10, 10, rc.right - 130, 25,
                       SWP_NOZORDER | SWP_NOREDRAW);

                   hDWP = DeferWindowPos(hDWP, GetDlgItem(hWnd, IDC_BTNADDENTRY), NULL,
                       rc.right - 110, 10, 100, 25,
                       SWP_NOZORDER | SWP_NOREDRAW);

                   hDWP = DeferWindowPos(hDWP, GetDlgItem(hWnd, IDC_TXTLOG), NULL,
                       10, 70, rc.right - 20, rc.bottom - 80,
                       SWP_NOZORDER | SWP_NOREDRAW);

                   // Resize all windows under the deferred window handled at the same time.

                   // We told DeferWindowPos not to redraw the controls so we can redraw
                   // them here all at once.
                   RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN |
                       RDW_ERASE | RDW_NOFRAME | RDW_UPDATENOW);
           return 0;

       // Handle the notifications of button presses.
       case WM_COMMAND:
           // If it was a button press and came from our button.

               INT nSelStart, nSelEnd;
               SCROLLINFO siLogVert;
               HWND hWndChild;
               LPTSTR lpBuffer;
               INT cchTextLen;

               // Allocate a buffer for our entry text.
               // The +2 is for an extra space we append and null terminator.
               hWndChild  = GetDlgItem(hWnd, IDC_TXTENTRY);
               cchTextLen = GetWindowTextLength(hWndChild);
               lpBuffer   = (LPTSTR)HeapAlloc(GetProcessHeap(),
                   HEAP_ZERO_MEMORY, (cchTextLen + 2) * sizeof(TCHAR));
               if(lpBuffer == NULL){
                   return 0;

               // Read our entry text.
               if(GetWindowText(hWndChild, lpBuffer, cchTextLen + 1)){
                   StrCat(lpBuffer, TEXT("\n"));

                   // Get our edit log window handle.
                   hWndChild = GetDlgItem(hWnd, IDC_TXTLOG);

                   // Tell edit control not to update the screen.
                   SendMessage(hWndChild, WM_SETREDRAW, FALSE, 0);

                   // Save our current selection.
                   nSelStart = nSelEnd = 0;
                   SendMessage(hWndChild, EM_GETSEL, (WPARAM)&nSelStart, (LPARAM)&nSelEnd);

                   // Save our current scroll info.
                   ZeroMemory(&siLogVert, sizeof(SCROLLINFO));
                   siLogVert.cbSize = sizeof(SCROLLINFO);
                   siLogVert.fMask  = SIF_PAGE | SIF_POS | SIF_RANGE;
                   GetScrollInfo(hWndChild, SB_VERT, &siLogVert);

                   // Update the log window by appending text to it.
                   cchTextLen = GetWindowTextLength(hWndChild);
                   SendMessage(hWndChild, EM_SETSEL, cchTextLen, cchTextLen);
                   SendMessage(hWndChild, EM_REPLACESEL, FALSE, (LPARAM)lpBuffer);

                       // Restore scroll position if not pinned.
                       SendMessage(hWndChild, WM_VSCROLL, MAKELONG(siLogVert.nPos,
                           SB_THUMBPOSITION), 0);
                   // Restore old text selection.
                   SendMessage(hWndChild, EM_SETSEL, nSelStart, nSelEnd);

                   // Update the state of the edit control on the screen.
                   SendMessage(hWndChild, WM_SETREDRAW, TRUE, 0);

                   // No text in the entry box?

               // Free temporary entry box allocation.
               HeapFree(GetProcessHeap(), 0, lpBuffer);
               return 0;

       case WM_DESTROY:
           // We post a WM_QUIT when our window is destroyed so we break the main message loop.

   // Not a message we wanted? No problem hand it over to the Default Window Procedure.
   return DefWindowProc(hWnd, uMsg, wParam, lParam);

// Program Entry Point
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, INT nShowCmd)
   DWORD dwExStyle;
   HDC hdcScreen;
   HWND hWnd;
   MSG msg;

   g_hInst = hInst;
   ZeroMemory(&msg,  sizeof(MSG));
   ZeroMemory(&wcex, sizeof(WNDCLASSEX));

   // Register our Main Window class.
   wcex.cbSize     = sizeof(WNDCLASSEX);
   wcex.hInstance   = hInst;
   wcex.lpszClassName = TEXT("MainWindow");
   wcex.lpfnWndProc   = MainWindowProc;
   wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
   wcex.hIcon       = LoadIcon(NULL, IDI_APPLICATION);
   wcex.hIconSm       = wcex.hIcon;
   wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
       return 1;

   // Create a font we can later use on our controls.
   hdcScreen = GetDC(HWND_DESKTOP);
   g_hfText = CreateFont(-MulDiv(11, GetDeviceCaps(hdcScreen, LOGPIXELSY), 72), // 11pt
   ReleaseDC(HWND_DESKTOP, hdcScreen);

   // Default main window ex-style.
   dwExStyle = WS_EX_APPWINDOW;

   // If we are using XP or above lets 'double-buffer' the window to reduce the
   // flicker to the edit controls when drawing (notepad needs this).
   lpVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
   if(GetVersionEx(&lpVer) && (lpVer.dwMajorVersion > 5 ||
       (lpVer.dwMajorVersion == 5 && lpVer.dwMinorVersion == 1)))
       dwExStyle |= WS_EX_COMPOSITED;

   // Create an instance of the Main Window.
   hWnd = CreateWindowEx(dwExStyle, wcex.lpszClassName, TEXT("Windows Chatbot Interface"),
       HWND_DESKTOP, NULL, hInst, NULL);

       // Show the main window and enter the message loop.
       ShowWindow(hWnd, nShowCmd);
       while(GetMessage(&msg, NULL, 0, 0))
           // If the message was not wanted by the Dialog Manager dispatch it like normal.
           if(!IsDialogMessage(hWnd, &msg)){

   // Free up our resources and return.
   return (int)msg.wParam;

Link to license:
Credit to: Napalm.  Original Title: Log Window Test App. Originally Written: 2010
Screenshot of modified version:  (See image attached below)
My Very Enormous Monster Just Stopped Using Nine