📜 ⬆️ ⬇️

Back to the future, or Hello World today and thirty years ago



Since today marks 30 years of waiting for the momentous future promised to us in the epochal film epopee “Back to the Future”, we also decided to recall a little how our products looked earlier and compare with what we have today.

Our department works with developers and one of our key products today is Windows 10, more precisely the development of the ecosystem around our new operating system and, in particular, the creation of universal applications.
')
Therefore, we decided to go back in time and see how the development tools, code samples and the SDK have changed in 30 years. And what could be more revealing than comparing the creation of the “Hello World” window application?

From Windows 1.0 to Windows 10


In the summer to the release of Windows 10, our friends from the OnTheHub company prepared a wonderful infographic from which you can follow the progress of the operating system itself.



I am sure that most hack readers are familiar with a significant part of this story on their own experience, so let's see what was there with the code?

Windows 1.0 SDK




The SDK for the first version of Windows was distributed on seven (7) five-inch floppy disks.

As Wikipedia quotes Charles Petzold, “the original version of the Hello World program in Windows 1.0 SDK was a bit scandalous. The HELLO.C file was about 150 lines long, and the HELLO.RC resource script took about 20 more lines ... Veteran programmers often frown in horror or, on the contrary, laugh when they encounter that hello-world program for Windows. ”The program code is shown below.

Ten years ago, Charles recalled the 20th anniversary of the SDK release, respectively, and wrote a very tasty article for history lovers about his impressions and attempts to write a new program twenty years later.

At that time, IBM, Digital Research and Microsoft released an SDK for their respective systems. They cost about $ 500, all were quite complicated, but, to be honest, Windows was the most prominent among them. It was not perfect, but it seemed that Microsoft really wanted independent software developers, like we did, to invest in writing Windows applications.

On seven diskettes were placed:


All examples, except the last, are written in C, sometimes with inserts in assembler.

The utilities "included a special version of Microsoft C Compiler 3.0, as well as two thick manuals of about 1000 pages in total, describing everything you needed to know to write Windows applications."

Speaking of cost ($ 500), Charles writes that the 80K header file was the most valuable, which was phenomenal at the time. In fact, he defined a software interface (API) for working with Windows, including a bunch of new data types, constants, structures, and a description of all the functions that were available to your applications (about 400 in total). And everything was perfectly documented in the manuals.

Windows 1.0: HELLO


The “project”, as we would say today, and then just the set of files with the Make-file for the assembly includes three code files:

Header file HELLO.h


/* String table constants */ #define IDSNAME 100 #define IDSABOUT 200 #define IDSTITLE 300 /* 'About' dialog box resource id */ #define ABOUTBOX 1 /* icon name */ #define HELLOICON 1 


HELLO.c program file


 /* Hello.c Hello Application Windows Toolkit Version 1.03 Copyright (c) Microsoft 1985,1986 */ #include "windows.h" #include "hello.h" char szAppName[10]; char szAbout[10]; char szMessage[15]; int MessageLength; static HANDLE hInst; FARPROC lpprocAbout; long FAR PASCAL HelloWndProc(HWND, unsigned, WORD, LONG); BOOL FAR PASCAL About( hDlg, message, wParam, lParam ) HWND hDlg; unsigned message; WORD wParam; LONG lParam; { if (message == WM_COMMAND) { EndDialog( hDlg, TRUE ); return TRUE; } else if (message == WM_INITDIALOG) return TRUE; else return FALSE; } void HelloPaint( hDC ) HDC hDC; { TextOut( hDC, (short)10, (short)10, (LPSTR)szMessage, (short)MessageLength ); } /* Procedure called when the application is loaded for the first time */ BOOL HelloInit( hInstance ) HANDLE hInstance; { PWNDCLASS pHelloClass; /* Load strings from resource */ LoadString( hInstance, IDSNAME, (LPSTR)szAppName, 10 ); LoadString( hInstance, IDSABOUT, (LPSTR)szAbout, 10 ); MessageLength = LoadString( hInstance, IDSTITLE, (LPSTR)szMessage, 15 ); pHelloClass = (PWNDCLASS)LocalAlloc( LPTR, sizeof(WNDCLASS) ); pHelloClass->hCursor = LoadCursor( NULL, IDC_ARROW ); pHelloClass->hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(HELLOICON) ); pHelloClass->lpszMenuName = (LPSTR)NULL; pHelloClass->lpszClassName = (LPSTR)szAppName; pHelloClass->hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH ); pHelloClass->hInstance = hInstance; pHelloClass->style = CS_HREDRAW | CS_VREDRAW; pHelloClass->lpfnWndProc = HelloWndProc; if (!RegisterClass( (LPWNDCLASS)pHelloClass ) ) /* Initialization failed. * Windows will automatically deallocate all allocated memory. */ return FALSE; LocalFree( (HANDLE)pHelloClass ); return TRUE; /* Initialization succeeded */ } int PASCAL WinMain( hInstance, hPrevInstance, lpszCmdLine, cmdShow ) HANDLE hInstance, hPrevInstance; LPSTR lpszCmdLine; int cmdShow; { MSG msg; HWND hWnd; HMENU hMenu; if (!hPrevInstance) { /* Call initialization procedure if this is the first instance */ if (!HelloInit( hInstance )) return FALSE; } else { /* Copy data from previous instance */ GetInstanceData( hPrevInstance, (PSTR)szAppName, 10 ); GetInstanceData( hPrevInstance, (PSTR)szAbout, 10 ); GetInstanceData( hPrevInstance, (PSTR)szMessage, 15 ); GetInstanceData( hPrevInstance, (PSTR)&MessageLength, sizeof(int) ); } hWnd = CreateWindow((LPSTR)szAppName, (LPSTR)szMessage, WS_TILEDWINDOW, 0, /* x - ignored for tiled windows */ 0, /* y - ignored for tiled windows */ 0, /* cx - ignored for tiled windows */ 0, /* cy - ignored for tiled windows */ (HWND)NULL, /* no parent */ (HMENU)NULL, /* use class menu */ (HANDLE)hInstance, /* handle to window instance */ (LPSTR)NULL /* no params to pass on */ ); /* Save instance handle for DialogBox */ hInst = hInstance; /* Bind callback function with module instance */ lpprocAbout = MakeProcInstance( (FARPROC)About, hInstance ); /* Insert "About..." into system menu */ hMenu = GetSystemMenu(hWnd, FALSE); ChangeMenu(hMenu, 0, NULL, 999, MF_APPEND | MF_SEPARATOR); ChangeMenu(hMenu, 0, (LPSTR)szAbout, IDSABOUT, MF_APPEND | MF_STRING); /* Make window visible according to the way the app is activated */ ShowWindow( hWnd, cmdShow ); UpdateWindow( hWnd ); /* Polling messages from event queue */ while (GetMessage((LPMSG)&msg, NULL, 0, 0)) { TranslateMessage((LPMSG)&msg); DispatchMessage((LPMSG)&msg); } return (int)msg.wParam; } /* Procedures which make up the window class. */ long FAR PASCAL HelloWndProc( hWnd, message, wParam, lParam ) HWND hWnd; unsigned message; WORD wParam; LONG lParam; { PAINTSTRUCT ps; switch (message) { case WM_SYSCOMMAND: switch (wParam) { case IDSABOUT: DialogBox( hInst, MAKEINTRESOURCE(ABOUTBOX), hWnd, lpprocAbout ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } break; case WM_DESTROY: PostQuitMessage( 0 ); break; case WM_PAINT: BeginPaint( hWnd, (LPPAINTSTRUCT)&ps ); HelloPaint( ps.hdc ); EndPaint( hWnd, (LPPAINTSTRUCT)&ps ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); break; } return(0L); } 

Looking at him, you can understand why Petzold spoke accordingly.

Resource file HELLO.rc


 #include "style.h" #include "hello.h" HELLOICON ICON hello.ico STRINGTABLE BEGIN IDSNAME, "Hello" IDSABOUT, "About..." IDSTITLE, "Hello Windows!" END ABOUTBOX DIALOG 22, 17, 154, 75 STYLE WS_POPUP | WS_DLGFRAME BEGIN CTEXT "Microsoft Windows" -1, 0, 5, 154, 8 ICON "hello" -1, 9, 23, 0, 0 CTEXT "Hello application" -1, 0, 14, 154, 8 CTEXT "Version 1.03" -1, 30, 34, 94, 8 CTEXT "Copyright 1985,1986, Microsoft Corp." -1, 0, 47,154, 9 DEFPUSHBUTTON "Ok" IDOK, 61, 59, 32, 14, WS_GROUP END 

As you can see from the source, in fact this is not a completely trivial application (for 170+ lines), which displays a simple phrase in the title or inside the application. In fact, it was somewhat more complicated: it also demonstrates how to work with lines from the resource file and also adds the About-item to the system menu that starts the dialog box when an item is selected, and using the callback function to process the result.

Last year, Charles wrote another article on the theme of “Hello World”, in which he describes his impressions of studying the program in 1985 and his thoughts on how to change it to make it easier for ordinary mortals. Three years later, in 1988, his first book “Programming Windows” will be released.

Windows 10 SDK


Over thirty years, software systems have come a long way. The complexity and quantity of the internal code has dramatically increased. The installer of a modern operating system can occupy a whole DVD with gigabytes of information. Comparatively weigh development tools and SDK with all the necessary libraries.

For example, the SDK for Windows 10 includes:
• Header files, libraries and metadata (with version!)
• Windows-contracts (metadata for Windows Runtime) with the corresponding platform files
• Extensions to the Windows platform - SDK for Windows Desktop, Windows Mobile, Windows IoT and Windows PPI.
• WindowsApp.lib - a common library for universal applications
• Merged CRT
• Windows App Certification Kit
• DirectX updates
• Windows Performance Toolkit
• .NET Framework 4.6 SDK
• Windows Accessibility Tools
• Links to sample code and documentation.

Over the years, relatively simple utilities for compiling and building applications have become a convenient Visual Studio environment for efficient application writing, working with code, debugging, ensuring team work — another huge new development compared to how programs were created thirty years ago.



Floppy disk largely replaced the delivery via the Internet. For example, downloading the SDK separately from Visual Studio, you first download a small bootloader, which weighs as much as half of those seven diskettes, and then you will be offered to download about 700 MB of installation files. The emulator for Windows 10 Mobile is another 1.5GB on top.

As the API evolved, it soon became apparent that all the documentation could not fit into a reasonable number of paper volumes. There was a time when the documentation for Windows was supplied on a separate CD / DVD, however, it is now available via the Internet and, accordingly, the MSDN website. Moreover, many sections of the documentation have been translated into widespread languages, including Russian.

Code examples can be found in MSDN Code Gallery or, as is customary in the developer community today, on GitHub . An interesting point that can be observed today in many IT communities is the participation of the community in forming relevant examples and making corrections and recommendations to the documentation.

I wonder if someone could have predicted such changes thirty years ago?

Windows 10: Hello World


I decided to try to write a kind of analogue to the “Hello World” application under Windows 10, using the new UWP platform and the JavaScript language (as closest to me). In general, this is such an interesting point that if 30 years ago pure C was the main language and almost all the examples were written on it, then today it is not only C / C ++, but also such “new” languages ​​like C #, VB and JavaScript (and even ObjC can be written for UWP!).

The first thing that catches the eye is the transition from a set of files to a project containing a much larger number of icons, and, in addition to resource files and files with application code, there is also a large description of the application itself and its settings (manifest).



It is also worth noting that the build procedure is “described” in the settings of the project itself (a kind of replacement for makefiles). And, unlike the time of thirty years ago, it has become much more complex. If I had written C ++ code, I would have to choose an assembly under x86, x64 or ARM instead of non-alternative 16bit, not to mention the many other parameters that are usually carefully hidden behind the banal pressing F5 or Shift + F5.

Resource resources.resjson file


In the case of a JavaScript project, the resource files (with automatic localization support!) Are regular JSON files:

 { "idsname" : "Hello", "idsabout" : "About...", "idstitle" : "Hello Windows!", "aboutbox.text" : "Microsoft Windows\nHello application\nVersion 10.03\nCopyright @2015, Microsoft Corp.", "aboutbox.button" : "Ok!" } 

Thirty years ago, there was no javascript, no xml, no json.

Page layout file default.html


Although the application can be “assembled” from the code, a significant part of the interface can now be described in a simpler and more visual declarative way. And here you can connect the data binding, including the resources:

 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>HelloWorld</title> <!-- WinJS references --> <link href="WinJS/css/ui-dark.css" rel="stylesheet" /> <script src="WinJS/js/base.js"></script> <script src="WinJS/js/ui.js"></script> <!-- HelloWorld references --> <link href="/css/default.css" rel="stylesheet" /> <script src="/js/default.js"></script> </head> <body class="win-type-body"> <nav> <a href="#" id="aboutMenu" data-win-res="{textContent: 'idsabout'}"></a> </nav> <p data-win-res="{textContent: 'idsname'}"></p> </body> </html> 

(Automatic) data binding is a huge modern development.

File with application logic default.js


The basic logic of a simple application can still be concentrated in one file (in more complex examples, like thirty years ago, you will most likely begin to decompose into various kinds of modules).

 (function () { "use strict"; var app = WinJS.Application; var activation = Windows.ApplicationModel.Activation; var appView = Windows.UI.ViewManagement.ApplicationView.getForCurrentView(); // Called on app activation app.onactivated = function (args) { // Initiate resources and UI -- all joined into a chain of promises var promise = new WinJS.Promise.join([ WinJS.Resources.processAll(), WinJS.UI.processAll() // Add basic logic ]).then(function () { // Update window title appView.title = WinJS.Resources.getString('idstitle').value; // Add click listener for menu "about" item document.getElementById("aboutMenu").addEventListener("click", (e) => showAboutDialog()); }); args.setPromise(promise); }; // Show"About" MessageDialog function showAboutDialog() { var messageDialog = new Windows.UI.Popups.MessageDialog( WinJS.Resources.getString('aboutbox.text').value, WinJS.Resources.getString('idsabout').value); // Dummy event handler for commands in dialog box var aboutHandler = (command) => { return true; }; messageDialog.commands.append( new Windows.UI.Popups.UICommand(WinJS.Resources.getString('aboutbox.button').value, aboutHandler)); messageDialog.showAsync(); } app.start(); })(); 

The application code was four times shorter (I also added some comments and blank lines), but the most important advantage of technology development is the greatly increased expressiveness of the API. In fact, many things that previously had to be done with “pens” today are hiding behind convenient calls to system or library functions.

Syntactic sugar, such as switch functions and the ability to use promise, make writing code and its readability much easier. By the way, a significant change is a transition to an asynchronous code model, hence promises and async.



Of course, my “update 30 years later” is not literal, but I think the general dynamics of changes in the approaches to creating applications is quite traceable. Today it looks like a completely new API, although every now and then, the ears of the old lamp Win32 or even of Windows.h are still slipping.

Source: https://habr.com/ru/post/269261/


All Articles