Recent

Author Topic: WinAPI - examples - post 2  (Read 5473 times)

440bx

  • Hero Member
  • *****
  • Posts: 3921
WinAPI - examples - post 2
« on: January 17, 2021, 08:38:45 am »
Hello,

The examples will be presented roughly in order of complexity, that is, from simplest to more complex.  The simplest are by far those APIs which should NOT be used since no example will be provided for those.

Amond the APIs that should be avoided and preferably never used are :

GlobalCompact
GlobalFix   
GlobalFlags 
GlobalHandle
GlobalLock   
GlobalReAlloc
GlobalSize   
GlobalUnfix 
GlobalUnlock
GlobalUnWire
GlobalWire   
LocalAlloc   
LocalCompact
LocalFlags   
LocalFree   
LocalHandle 
LocalLock   
LocalReAlloc
LocalShrink 
LocalSize   
LocalUnlock 

All of the above are Windows 16 bit memory management functions which are _not_ well suited for a 32 bit O/S.  Use the 32 bit memory management functions instead.

As mentioned previously, no example for any of the above APIs will be given.



GlobalAlloc
GlobalFree

These two (2) APIs are still commonly found in C programs but, are not as flexible as HeapAlloc() and HeapFree() which should be preferred.

No example of GlobalAlloc and GlobalFree will be given.  An example of HeapAlloc and HeapFree will be given in the future.


GlobalMemoryStatus

GlobalMemoryStatus returns incorrect information on systems with more than 4GB of memory. Use GlobalMemoryStatusEx instead.

An example for both will be given in the future.


GetTextExtentPoint

Use GetTextExtentPoint32 instead which, according to MS, is more accurate.





This post is for examples of API used in the great majority of the examples. Examples attached to this post are :

WinAPI - GetTextExtentPoint      (gdi)
WinAPI - GetTextExtentPoint32  (gdi)

Both of these APIs return the width and height in pixels of a specified string


WinAPI - SetBkMode                    (gdi)

Sets the background color to opaque or transparent.  When the background is opaque then whatever color was chosen as background will be visible.


WinAPI - SetTextAlign                 (gdi)

Sets the text alignment.  This example visually demonstrates the effects of some of the SetTextAlign options. See MSDN for all available options.


WinAPI - TextOut                        (gdi)

Outputs a string at the specified location, using the currently selected font, background color, and text color.


WinAPI - GetClientRect               (user)

Retrieves the coordinates of the client area.  This example draws a frame around the client area.  It also serves as an example of CreatePen, SetCapture, ReleaseCapture, InvalidateRect, SelectObject, Rectangle, lstrcpy, lstrlen and DeleteObject.

NOTE: this example does not include code to eliminate or minimize flicker,which would not be hard to implement (left for future example.)



WinAPI - Windows Bitness       (technique)

This version includes minor editing of the comments and loads csrss.exe as an image resource instead of a data file.  Since Windows uses the low bits of the load address to indicate the mode the file was loaded in, this version aligns the load address instead of simply subtracting one (1) which is valid only when the module is loaded as a data file.  Using alignment works regardless of the way the module is loaded.

recommendation : replace the previous version with this version.



What follows is the code for the GetClientRect example (the source for the remaining examples is present in the zip file attached to this post.)
Code: Pascal  [Select][+][-]
  1. {$APPTYPE        GUI}
  2.  
  3. {$LONGSTRINGS    OFF}
  4. {$WRITEABLECONST ON}
  5. {$DESCRIPTION    'Win32 API function - GetClientRect example'}
  6.  
  7. {$R GetClientRect.Res}
  8.  
  9. program _GetClientRect;
  10.   { Win32 API function - GetClientRect example                                }
  11.  
  12. uses Windows, Messages, Resource, SysUtils;
  13.  
  14. const
  15.   AppNameBase  = 'GetClientRect Example';
  16.  
  17.   {$ifdef WIN64}
  18.     Bitness64  = ' - 64bit';
  19.     AppName    = AppNameBase + Bitness64;
  20.   {$else}
  21.     Bitness32  = ' - 32bit';
  22.     AppName    = AppNameBase + Bitness32;
  23.   {$endif}
  24.  
  25.   AboutBox     = 'AboutBox';
  26.   APPICON      = 'APPICON';
  27.   APPMENU      = 'APPMENU';
  28.  
  29. {-----------------------------------------------------------------------------}
  30.  
  31. {$ifdef VER90} { Delphi 2.0 }
  32. type
  33.   ptrint  = longint;
  34.   ptruint = dword;
  35. {$endif}
  36.  
  37. {-----------------------------------------------------------------------------}
  38.  
  39. function About(DlgWnd : hWnd; Msg : UINT; wParam, lParam : ptrint)
  40.          : ptrint; stdcall;
  41. begin
  42.   About := ord(TRUE);
  43.  
  44.   case msg of
  45.  
  46.     WM_INITDIALOG: exit;
  47.  
  48.     WM_COMMAND:
  49.     begin
  50.       if (LOWORD(wParam) = IDOK) or (LOWORD(wParam) = IDCANCEL) then
  51.       begin
  52.         EndDialog(DlgWnd, ord(TRUE));
  53.  
  54.         exit;
  55.       end;
  56.     end;
  57.   end;
  58.  
  59.   About := ord(FALSE);
  60. end;
  61.  
  62. {-----------------------------------------------------------------------------}
  63.  
  64. function WndProc (Wnd : hWnd; Msg : UINT; wParam, lParam : ptrint)
  65.          : ptrint; stdcall;
  66.   { main application/window handler function                                  }
  67. const
  68.   GetClientRect_Call = 'GetClientRect (Wnd : HWND; var Rect : TRECT) : BOOL;';
  69.  
  70.   Pen                : HPEN = 0;      { deleted when the window is destroyed  }
  71.  
  72.   Hint = 'Press the Left mouse button anywhere in the client area';
  73.  
  74.   Tracking           : BOOL = FALSE;
  75.  
  76. var
  77.   ps                 : TPAINTSTRUCT;
  78.  
  79.   ClientRect         : TRECT;
  80.  
  81.   Buf                : packed array[0..255] of char;
  82.  
  83.   TextSize           : TSIZE;
  84.   OldPen             : HPEN;
  85.  
  86. begin
  87.   WndProc := 0;
  88.  
  89.   case Msg of
  90.     WM_CREATE:
  91.     begin
  92.       {-----------------------------------------------------------------------}
  93.       { Using "not GetSysColor(COLOR_WINDOW)" guarantees that the pen will    }
  94.       { be created using a color that will always be visible.  Note that      }
  95.       { for this to be true, the value passed to GetSysColor must be the      }
  96.       { same as the one passed when the class was registered.                 }
  97.  
  98.       { We AND with $00FFFFFF to make sure that the high byte is zero.        }
  99.       { Windows uses this byte to select a palette which is not something     }
  100.       { we want it to do in this occasion.                                    }
  101.  
  102.       Pen := CreatePen(PS_INSIDEFRAME,
  103.                        3,
  104.                        not GetSysColor(COLOR_WINDOW) and $00FFFFFF);
  105.       exit;
  106.     end;
  107.  
  108.     WM_LBUTTONDOWN:
  109.     begin
  110.       {-----------------------------------------------------------------------}
  111.       { capture the mouse to make sure we always get the button up which      }
  112.       { is the signal to refresh the client area.                             }
  113.  
  114.       SetCapture(Wnd);
  115.       Tracking := TRUE;
  116.       InvalidateRect(Wnd, nil, TRUE);
  117.  
  118.       exit;
  119.     end;
  120.  
  121.     WM_LBUTTONUP:
  122.     begin
  123.       {-----------------------------------------------------------------------}
  124.       { if the mouse was not captured then we don't have anything to do       }
  125.  
  126.       if Tracking then
  127.       begin
  128.         ReleaseCapture;                   { let the cat play with it          }
  129.  
  130.         Tracking := FALSE;
  131.         InvalidateRect(Wnd, nil, TRUE);   { redraw the client area            }
  132.       end;
  133.  
  134.       exit;
  135.     end;
  136.  
  137.     WM_PAINT:
  138.     begin
  139.       BeginPaint(Wnd, ps);
  140.  
  141.       { set up the dc                                                         }
  142.  
  143.       SetBkMode(ps.hdc, TRANSPARENT);
  144.       SetTextAlign(ps.hdc, TA_CENTER);
  145.  
  146.       GetClientRect(Wnd, ClientRect);       { we'll use this quite often      }
  147.  
  148.       if Tracking then
  149.       begin
  150.         {---------------------------------------------------------------------}
  151.         { we have the mouse captured. we draw a frame around the client       }
  152.         { rectangle and display its size.                                     }
  153.  
  154.         OldPen := SelectObject(ps.hdc, Pen);
  155.         SelectObject(ps.hdc, GetStockObject(NULL_BRUSH));
  156.  
  157.         {---------------------------------------------------------------------}
  158.         { draw a frame around the client area. This could be done using       }
  159.         { the FrameRect API instead of Rectangle.                             }
  160.  
  161.         with ClientRect do
  162.         begin
  163.           Rectangle(ps.hdc, Left, Top, Right, Bottom);
  164.         end;
  165.  
  166.         {---------------------------------------------------------------------}
  167.         { draw the size of the client area                                    }
  168.  
  169.         SelectObject(ps.hdc, OldPen);
  170.  
  171.         with ClientRect do
  172.         begin
  173.           StrFmt(Buf,
  174.                  '(Left, Top) (%d, %d) - (Right, Bottom) (%d, %d)',
  175.                  [Left, Top, Right, Bottom]);
  176.         end;
  177.  
  178.         { the code outside the if statement will output the buffer            }
  179.       end
  180.       else
  181.       begin
  182.         {---------------------------------------------------------------------}
  183.         { we don't have the mouse captured.  we draw a string giving          }
  184.         { the user a hint about what to do next.                              }
  185.  
  186.         lstrcpy(Buf, Hint);
  187.       end;
  188.  
  189.       {-----------------------------------------------------------------------}
  190.       { calculate the size of the output string currently in Buf              }
  191.  
  192.       GetTextExtentPoint32(ps.hdc,
  193.                            Buf,
  194.                            lstrlen(Buf), TextSize);
  195.       TextOut(ps.hdc,
  196.               ClientRect.Right  div 2,
  197.               ClientRect.Bottom div 2 - TextSize.cy,
  198.               Buf,
  199.               lstrlen(Buf));
  200.  
  201.       {-----------------------------------------------------------------------}
  202.       { draw the function call                                                }
  203.  
  204.       SelectObject(ps.hdc, GetStockObject(DEFAULT_GUI_FONT));
  205.       SetTextAlign(ps.hdc, TA_CENTER or TA_BOTTOM);
  206.  
  207.       lstrcpy(Buf, GetClientRect_Call);
  208.  
  209.       { calculate the size of the output string                               }
  210.  
  211.       GetTextExtentPoint32(ps.hdc,
  212.                            Buf,
  213.                            lstrlen(Buf), TextSize);
  214.       TextOut(ps.hdc,
  215.               ClientRect.Right div 2,
  216.               ClientRect.Bottom - TextSize.cy,
  217.               Buf,
  218.               lstrlen(Buf));
  219.  
  220.       {-----------------------------------------------------------------------}
  221.       { we're done painting                                                   }
  222.  
  223.       EndPaint(Wnd, ps);
  224.  
  225.       exit;
  226.     end;
  227.  
  228.     WM_COMMAND:
  229.     begin
  230.       case LOWORD(wParam) of
  231.         IDM_ABOUT:
  232.         begin
  233.           DialogBox(hInstance, ABOUTBOX, Wnd, @About);
  234.  
  235.           exit;
  236.         end; { IDM_ABOUT }
  237.  
  238.         IDM_EXIT:
  239.         begin
  240.           DestroyWindow(Wnd);
  241.  
  242.           exit;
  243.         end; { IDM_EXIT }
  244.       end; { case LOWORD(wParam) }
  245.     end; { WM_COMMAND }
  246.  
  247.     WM_DESTROY:
  248.     begin
  249.       if Pen <> 0 then DeleteObject(Pen);
  250.  
  251.  
  252.       PostQuitMessage(0);
  253.  
  254.       exit;
  255.     end; { WM_DESTROY }
  256.   end; { case msg }
  257.  
  258.   WndProc := DefWindowProc (Wnd, Msg, wParam, lParam);
  259. end;
  260.  
  261. {-----------------------------------------------------------------------------}
  262.  
  263. function InitAppClass : WordBool;
  264.   { registers the application's window classes                                }
  265. var
  266.   cls : TWndClassEx;
  267.  
  268. begin
  269.   cls.cbSize          := sizeof(TWndClassEx);         { must be initialized   }
  270.  
  271.   if not GetClassInfoEx (hInstance, AppName, cls) then
  272.   begin
  273.     with cls do begin
  274.       { cbSize has already been initialized as required above                 }
  275.  
  276.       style           := CS_BYTEALIGNCLIENT;
  277.       lpfnWndProc     := @WndProc;                    { window class handler  }
  278.       cbClsExtra      := 0;
  279.       cbWndExtra      := 0;
  280.       hInstance       := system.hInstance;            { qualify instance!     }
  281.       hIcon           := LoadIcon (hInstance, APPICON);
  282.       hCursor         := LoadCursor(0, idc_arrow);
  283.       hbrBackground   := GetSysColorBrush(COLOR_WINDOW);
  284.       lpszMenuName    := APPMENU;                     { Menu name             }
  285.       lpszClassName   := AppName;                     { Window Class name     }
  286.       hIconSm         := LoadImage(hInstance,
  287.                                    APPICON,
  288.                                    IMAGE_ICON,
  289.                                    16,
  290.                                    16,
  291.                                    LR_DEFAULTCOLOR);
  292.     end; { with }
  293.  
  294.     InitAppClass := WordBool(RegisterClassEx(cls));
  295.   end
  296.   else InitAppClass := true;
  297. end;
  298.  
  299. {-----------------------------------------------------------------------------}
  300.  
  301. function WinMain : integer;
  302.   { application entry point                                                   }
  303. var
  304.   Wnd : hWnd;
  305.   Msg : TMsg;
  306.  
  307. begin
  308.   if not InitAppClass then Halt (255);  { register application's class        }
  309.  
  310.   { Create the main application window                                        }
  311.  
  312.   Wnd := CreateWindowEx(WS_EX_CLIENTEDGE,
  313.                         AppName,                { class name                  }
  314.                         AppName,                { window caption text         }
  315.                         ws_Overlapped       or  { window style                }
  316.                         ws_SysMenu          or
  317.                         ws_MinimizeBox      or
  318.                         ws_ClipSiblings     or
  319.                         ws_ClipChildren     or  { don't affect children       }
  320.                         ws_visible,             { make showwindow unnecessary }
  321.                         50,                     { x pos on screen             }
  322.                         50,                     { y pos on screen             }
  323.                         400,                    { window width                }
  324.                         300,                    { window height               }
  325.                         0,                      { parent window handle        }
  326.                         0,                      { menu handle 0 = use class   }
  327.                         hInstance,              { instance handle             }
  328.                         Nil);                   { parameter sent to WM_CREATE }
  329.  
  330.   if Wnd = 0 then Halt;                         { could not create the window }
  331.  
  332.   while GetMessage (Msg, 0, 0, 0) do            { wait for message            }
  333.   begin
  334.     TranslateMessage (Msg);                     { key conversions             }
  335.     DispatchMessage  (Msg);                     { send to window procedure    }
  336.   end;
  337.  
  338.   WinMain := Msg.wParam;                        { terminate with return code  }
  339. end;
  340.  
  341. begin
  342.   WinMain;
  343. end.
  344.  
This example also shows how and when to capture the mouse to cause it to update the client area when necessary.  It also serves as an example for CreatePen, SelectObject, Rectangle and DeleteObject.

« Last Edit: January 17, 2021, 08:47:22 am by 440bx »
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

FlierMate

  • Guest
Re: WinAPI - examples - post 2
« Reply #1 on: January 21, 2021, 12:09:54 pm »
Please allow me to ask two general questions here:

1. Can we say Windows API is a "framework"?

2. Windows API is at the lowest level. Does that mean literally nobody knows how Windows execute the API call?




440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: WinAPI - examples - post 2
« Reply #2 on: January 21, 2021, 12:57:45 pm »
Please allow me to ask two general questions here:

1. Can we say Windows API is a "framework"?

2. Windows API is at the lowest level. Does that mean literally nobody knows how Windows execute the API call?
All questions are welcome.

To the first question, I don't consider the Windows API a framework because, unlike in a framework, a great number of APIs are completely independent of each other.  A framework usually incorporates a significant number of dependencies among the facilities it provides, e.g, .net.

To the second question, a lot of people know _exactly_ how Windows executes its API functions.  A lot of API functions can be traced through using an application debugger.  APIs that cause a ring transition, that is from ring-3 to ring-0, can be traced through using a system debugger.  Another way to see exactly what an API does and, how it does it, is to disassemble the DLL that contains it.

In summary, except for ring transition code and code that executes in ring 0, there is nothing particularly different between Windows API functions and run of the mill code that can be found in application code.  For instance, an API such as DebugBreak() can be written as a Pascal assembler routine in just two lines of assembly code.  Other APIs would require more code and yet other APIs would require calling functions present in Ntdll to trigger execution of ring-0 code (though, even those could be coded in Pascal but, why re-invent the wheel.)

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
Re: WinAPI - examples - post 2
« Reply #3 on: January 21, 2021, 01:57:29 pm »
2. Windows API is at the lowest level. Does that mean literally nobody knows how Windows execute the API call?

In addition to what 440bx said: if you're really curious you can look around in ReactOS' source code and find out how some calls are implemented (I've done that in the past a few times to find out how some API functions work).

FlierMate

  • Guest
Re: WinAPI - examples - post 2
« Reply #4 on: January 21, 2021, 02:32:42 pm »

In addition to what 440bx said: if you're really curious you can look around in ReactOS' source code and find out how some calls are implemented

Whoa, I completely forgot an operating system is written NOT in Assembly language.

ReactOS was written in C...

All questions are welcome.

Thank you for the assurance.

Another way to see exactly what an API does and, how it does it, is to disassemble the DLL that contains it.

Never thought of that. I am delighted to know this.

For instance, an API such as DebugBreak() can be written as a Pascal assembler routine in just two lines of assembly code. 

This makes sense to me.

(I've done that in the past a few times to find out how some API functions work).

This means an operating system is not a secret. (I am new to the design of OS and just at very beginning level of design of compiler.) Besides CPU itself, an operating system is such a massive and intelligent work by men.

As an off-topic question: I often saw someone comes up with real-time operating system on freelancer hiring website, is it a hoax? 

It was thrilling to discover ReactOS open-source page. All contributors deserve respect!

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: WinAPI - examples - post 2
« Reply #5 on: January 21, 2021, 04:27:21 pm »
As an off-topic question: I often saw someone comes up with real-time operating system on freelancer hiring website, is it a hoax?

Why would it be? Lots of people and business need real time OSs and there is not always one readily available for download/purchase; the obvious solution then is to contract some freelancer and pay them (oftentimes through the nose ;)) to build one, more or so as they usually have a very specific scope and need not be what we might term a "general purpose" OS. In fact, OS and application are frequently so interwoven that it's not very clear where one ends and the other starts.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

FlierMate

  • Guest
Re: WinAPI - examples - post 2
« Reply #6 on: January 21, 2021, 05:29:35 pm »
Why would it be? Lots of people and business need real time OSs and there is not always one readily available for download/purchase; the obvious solution then is to contract some freelancer and pay them (oftentimes through the nose ;)) to build one, more or so as they usually have a very specific scope and need not be what we might term a "general purpose" OS. In fact, OS and application are frequently so interwoven that it's not very clear where one ends and the other starts.

I have better understanding now. Thanks lucamar.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
Re: WinAPI - examples - post 2
« Reply #7 on: January 22, 2021, 09:09:40 am »
In addition to what 440bx said: if you're really curious you can look around in ReactOS' source code and find out how some calls are implemented

Whoa, I completely forgot an operating system is written NOT in Assembly language.

ReactOS was written in C...

Windows itself is written in C as well. As is Linux. There are also OSes written in Pascal. Or essentially any language that can compile binary code. And yes, there are also examples in assembly language. ;)

As an off-topic question: I often saw someone comes up with real-time operating system on freelancer hiring website, is it a hoax?

Depends on whether the developers know what they're doing. At work we have a custom realtime, microkernel operating system as well. ;)

FlierMate

  • Guest
Re: WinAPI - examples - post 2
« Reply #8 on: March 01, 2021, 02:40:30 pm »
2. Windows API is at the lowest level. Does that mean literally nobody knows how Windows execute the API call?

In addition to what 440bx said: if you're really curious you can look around in ReactOS' source code and find out how some calls are implemented (I've done that in the past a few times to find out how some API functions work).

Hi PascalDragon and 440bx. I took about an hour to search and try to gain preliminary understanding about ReactOS in particular WriteConsoleA. I noticed that it uses RtlCopyMemory() function and I was not able to locate this function anywhere in the ReactOS kernel.

Can you please help to locate which .c file contains this RtlCopyMemory function? I found some soundalike and lookalike functions but none are exactly spelled as RtlCopyMemory.

Does that mean Windows (or React OS) has direct screen buffer access (WriteConsoleA in this case) and that the OS prohibits end -user from accessing the video memory? Unlike back in DOS era, programmers can read from and write to B800:0 (80x25 x 2) and A000:0 (graphics memory).

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: WinAPI - examples - post 2
« Reply #9 on: March 01, 2021, 03:21:21 pm »
Does that mean Windows (or React OS) has direct screen buffer access (WriteConsoleA in this case) and that the OS prohibits end -user from accessing the video memory? Unlike back in DOS era, programmers can read from and write to B800:0 (80x25 x 2) and A000:0 (graphics memory).

I don't know about more modern Windows but we have a program running on Windows 2K and XP which does exactly that for console output (through B800). Only, IIRC (I'm not the responsible for that program anymore), the program has to be run under very specific conditions: full screen, un-windowed, with a special info file (.PIF), ... and don't remember what else we had to do (something about the video mode, I think).

But that is for somewhat special "industrial PCs" resembling thickly rugerized tablets more than anything else, and they might have special hardware or drivers or whatnots, so YMMV!
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: WinAPI - examples - post 2
« Reply #10 on: March 01, 2021, 04:57:12 pm »
I noticed that it uses RtlCopyMemory() function and I was not able to locate this function anywhere in the ReactOS kernel.
RtlCopyMemory is found in the 64bit version of NTDLL and _not_ found in the 32bit version.  Also, in 64bit just FYI, RtlCopyMemory, RtlMoveMemory, memcpy and memmov are the same function (the export entries all point to the same routine.)  In 32bit, every one of those functions (those that exist) have their own implementation. 

Can you please help to locate which .c file contains this RtlCopyMemory function? I found some soundalike and lookalike functions but none are exactly spelled as RtlCopyMemory.
It's quite possible that RtlCopyMemory is not present in ReactOS since it is _not_ present in the 32bit version of NTDLL in Windows.  You can use RtlMoveMemory instead which effectively makes a copy of whatever is moved (it doesn't clear the source buffer, thus the target of the move is a copy.)

Does that mean Windows (or React OS) has direct screen buffer access (WriteConsoleA in this case) and that the OS prohibits end -user from accessing the video memory? Unlike back in DOS era, programmers can read from and write to B800:0 (80x25 x 2) and A000:0 (graphics memory).
The answer to that is yes and no.  If the application is a dos application then it is run in a dos VM in full screen.  Since the program is running in a VM its video memory is virtualized and pretty much works just as it would under dos.  The "No" part comes when dealing with a 32bit or 64bit console application.  Those are _not_ virtualized instead they are clients of the facility Windows provides to emulate a character subsystem (conhost.exe in Win7+ and a different thing I don't remember at this time in WinXP.)  The application has access to the video buffer but in a different way than it is done under dos.  Specifically, the video buffer could be anywhere in memory and the character emulator has to be "informed" that it should display on screen whatever is in the buffer by means of console functions.

HTH.

In case you are interested, what follows is the 64bit implementation of RtlCopyMemory (and its synonyms, of course) :
Code: ASM  [Select][+][-]
  1. ; Exported entry 685. RtlCopyMemory
  2. ; Exported entry 1041. RtlMoveMemory
  3. ; Exported entry 1926. memcpy
  4. ; Exported entry 1928. memmove
  5.  
  6. ; =============== S U B R O U T I N E =======================================
  7.  
  8.  
  9. ; void *__cdecl memmove(void *, const void *, size_t)
  10.                 public memmove
  11. memmove         proc near               ; CODE XREF: RtlpEnsureBufferSize+6Fp
  12.                                         ; RtlpQueryInformationActivationContextDetailedInformation+1F9p ...
  13.                 mov     r11, rcx        ; RtlCopyMemory
  14.                                         ; RtlMoveMemory
  15.                                         ; memcpy
  16.                 sub     rdx, rcx
  17.                 jb      loc_78E9E89A
  18.                 cmp     r8, 8
  19.                 jb      short loc_78E9E764
  20.                 test    cl, 7
  21.                 jz      short loc_78E9E73E
  22.                 test    cl, 1
  23.                 jz      short loc_78E9E718
  24.                 mov     al, [rdx+rcx]
  25.                 dec     r8
  26.                 mov     [rcx], al
  27.                 add     rcx, 1
  28.  
  29. loc_78E9E718:                           ; CODE XREF: memmove+1Aj
  30.                 test    cl, 2
  31.                 jz      short loc_78E9E72C
  32.                 mov     ax, [rdx+rcx]
  33.                 sub     r8, 2
  34.                 mov     [rcx], ax
  35.                 add     rcx, 2
  36.  
  37. loc_78E9E72C:                           ; CODE XREF: memmove+2Bj
  38.                 test    cl, 4
  39.                 jz      short loc_78E9E73E
  40.                 mov     eax, [rcx+rdx]
  41.                 sub     r8, 4
  42.                 mov     [rcx], eax
  43.                 add     rcx, 4
  44.  
  45. loc_78E9E73E:                           ; CODE XREF: memmove+15j memmove+3Fj ...
  46.                 mov     r9, r8
  47.                 shr     r9, 5
  48.                 jnz     short loc_78E9E797
  49.  
  50. loc_78E9E747:                           ; CODE XREF: memmove+E0j
  51.                 mov     r9, r8
  52.                 shr     r9, 3
  53.                 jz      short loc_78E9E764
  54.  
  55. loc_78E9E750:                           ; CODE XREF: memmove+6Ej
  56.                 mov     rax, [rdx+rcx]
  57.                 mov     [rcx], rax
  58.                 add     rcx, 8
  59.                 dec     r9
  60.                 jnz     short loc_78E9E750
  61.                 and     r8, 7
  62.  
  63. loc_78E9E764:                           ; CODE XREF: memmove+10j memmove+5Ej
  64.                 test    r8, r8
  65.                 jnz     short loc_78E9E770
  66.                 mov     rax, r11
  67.                 retn
  68. ; ---------------------------------------------------------------------------
  69.                 align 10h
  70.  
  71. loc_78E9E770:                           ; CODE XREF: memmove+77j memmove+8Bj
  72.                 mov     al, [rdx+rcx]
  73.                 mov     [rcx], al
  74.                 inc     rcx
  75.                 dec     r8
  76.                 jnz     short loc_78E9E770
  77.                 mov     rax, r11
  78.                 retn
  79. ; ---------------------------------------------------------------------------
  80.                 db 7 dup(66h), 0Fh, 1Fh, 84h, 5 dup(0)
  81.                 db 3 dup(66h), 90h
  82.                 db 2 dup(66h), 90h
  83. ; ---------------------------------------------------------------------------
  84.  
  85. loc_78E9E797:                           ; CODE XREF: memmove+55j
  86.                 cmp     r9, 2000h
  87.                 jnb     short loc_78E9E7E2
  88.  
  89. loc_78E9E7A0:                           ; CODE XREF: memmove+DAj memmove+F9j
  90.                 mov     rax, [rdx+rcx]
  91.                 mov     r10, [rdx+rcx+8]
  92.                 add     rcx, 20h
  93.                 mov     [rcx-20h], rax
  94.                 mov     [rcx-18h], r10
  95.                 mov     rax, [rdx+rcx-10h]
  96.                 mov     r10, [rdx+rcx-8]
  97.                 dec     r9
  98.                 mov     [rcx-10h], rax
  99.                 mov     [rcx-8], r10
  100.                 jnz     short loc_78E9E7A0
  101.                 and     r8, 1Fh
  102.                 jmp     loc_78E9E747
  103. ; ---------------------------------------------------------------------------
  104.                 db 3 dup(66h), 0Fh, 1Fh, 84h, 5 dup(0)
  105.                 db 66h, 90h
  106. ; ---------------------------------------------------------------------------
  107.  
  108. loc_78E9E7E2:                           ; CODE XREF: memmove+AEj
  109.                 cmp     rdx, 1000h
  110.                 jb      short loc_78E9E7A0
  111.  
  112. loc_78E9E7EB:                           ; CODE XREF: memmove+184j
  113.                 mov     eax, 20h
  114.  
  115. loc_78E9E7F0:                           ; CODE XREF: memmove+112j
  116.                 prefetchnta byte ptr [rdx+rcx]
  117.                 prefetchnta byte ptr [rdx+rcx+40h]
  118.                 add     rcx, 80h
  119.                 dec     eax
  120.                 jnz     short loc_78E9E7F0
  121.                 sub     rcx, 1000h
  122.                 mov     eax, 40h
  123.  
  124. loc_78E9E810:                           ; CODE XREF: memmove+174j
  125.                 mov     r9, [rdx+rcx]
  126.                 mov     r10, [rdx+rcx+8]
  127.                 movnti  qword ptr [rcx], r9
  128.                 movnti  qword ptr [rcx+8], r10
  129.                 mov     r9, [rdx+rcx+10h]
  130.                 mov     r10, [rdx+rcx+18h]
  131.                 movnti  qword ptr [rcx+10h], r9
  132.                 movnti  qword ptr [rcx+18h], r10
  133.                 mov     r9, [rdx+rcx+20h]
  134.                 mov     r10, [rdx+rcx+28h]
  135.                 add     rcx, 40h
  136.                 movnti  qword ptr [rcx-20h], r9
  137.                 movnti  qword ptr [rcx-18h], r10
  138.                 mov     r9, [rdx+rcx-10h]
  139.                 mov     r10, [rdx+rcx-8]
  140.                 dec     eax
  141.                 movnti  qword ptr [rcx-10h], r9
  142.                 movnti  qword ptr [rcx-8], r10
  143.                 jnz     short loc_78E9E810
  144.                 sub     r8, 1000h
  145.                 cmp     r8, 1000h
  146.                 jnb     loc_78E9E7EB
  147.                 lock or byte ptr [rsp+0], 0
  148.                 jmp     loc_78E9E73E
  149. ; ---------------------------------------------------------------------------
  150.                 db 4 dup(66h), 0Fh, 1Fh, 84h, 5 dup(0)
  151.                 db 3 dup(66h), 90h
  152.                 db 3 dup(66h), 90h
  153.                 db 66h, 90h
  154. ; ---------------------------------------------------------------------------
  155.  
  156. loc_78E9E89A:                           ; CODE XREF: memmove+6j
  157.                 add     rcx, r8
  158.                 cmp     r8, 8
  159.                 jb      short loc_78E9E904
  160.                 test    cl, 7
  161.                 jz      short loc_78E9E8DE
  162.                 test    cl, 1
  163.                 jz      short loc_78E9E8B8
  164.                 dec     rcx
  165.                 mov     al, [rdx+rcx]
  166.                 dec     r8
  167.                 mov     [rcx], al
  168.  
  169. loc_78E9E8B8:                           ; CODE XREF: memmove+1BBj
  170.                 test    cl, 2
  171.                 jz      short loc_78E9E8CC
  172.                 sub     rcx, 2
  173.                 mov     ax, [rdx+rcx]
  174.                 sub     r8, 2
  175.                 mov     [rcx], ax
  176.  
  177. loc_78E9E8CC:                           ; CODE XREF: memmove+1CBj
  178.                 test    cl, 4
  179.                 jz      short loc_78E9E8DE
  180.                 sub     rcx, 4
  181.                 mov     eax, [rcx+rdx]
  182.                 sub     r8, 4
  183.                 mov     [rcx], eax
  184.  
  185. loc_78E9E8DE:                           ; CODE XREF: memmove+1B6j memmove+1DFj ...
  186.                 mov     r9, r8
  187.                 shr     r9, 5
  188.                 jnz     short loc_78E9E937
  189.  
  190. loc_78E9E8E7:                           ; CODE XREF: memmove+27Fj
  191.                 mov     r9, r8
  192.                 shr     r9, 3
  193.                 jz      short loc_78E9E904
  194.  
  195. loc_78E9E8F0:                           ; CODE XREF: memmove+20Ej
  196.                 sub     rcx, 8
  197.                 mov     rax, [rdx+rcx]
  198.                 dec     r9
  199.                 mov     [rcx], rax
  200.                 jnz     short loc_78E9E8F0
  201.                 and     r8, 7
  202.  
  203. loc_78E9E904:                           ; CODE XREF: memmove+1B1j memmove+1FEj
  204.                 test    r8, r8
  205.                 jnz     short loc_78E9E910
  206.                 mov     rax, r11
  207.                 retn
  208. ; ---------------------------------------------------------------------------
  209.                 align 10h
  210.  
  211. loc_78E9E910:                           ; CODE XREF: memmove+217j memmove+22Bj
  212.                 dec     rcx
  213.                 mov     al, [rdx+rcx]
  214.                 dec     r8
  215.                 mov     [rcx], al
  216.                 jnz     short loc_78E9E910
  217.                 mov     rax, r11
  218.                 retn
  219. ; ---------------------------------------------------------------------------
  220.                 db 7 dup(66h), 0Fh, 1Fh, 84h, 5 dup(0)
  221.                 db 3 dup(66h), 90h
  222.                 db 2 dup(66h), 90h
  223. ; ---------------------------------------------------------------------------
  224.  
  225. loc_78E9E937:                           ; CODE XREF: memmove+1F5j
  226.                 cmp     r9, 2000h
  227.                 jnb     short loc_78E9E982
  228.  
  229. loc_78E9E940:                           ; CODE XREF: memmove+279j memmove+299j
  230.                 mov     rax, [rdx+rcx-8]
  231.                 mov     r10, [rdx+rcx-10h]
  232.                 sub     rcx, 20h
  233.                 mov     [rcx+18h], rax
  234.                 mov     [rcx+10h], r10
  235.                 mov     rax, [rdx+rcx+8]
  236.                 mov     r10, [rdx+rcx]
  237.                 dec     r9
  238.                 mov     [rcx+8], rax
  239.                 mov     [rcx], r10
  240.                 jnz     short loc_78E9E940
  241.                 and     r8, 1Fh
  242.                 jmp     loc_78E9E8E7
  243. ; ---------------------------------------------------------------------------
  244.                 db 4 dup(66h), 0Fh, 1Fh, 84h, 5 dup(0)
  245.                 db 66h, 90h
  246. ; ---------------------------------------------------------------------------
  247.  
  248. loc_78E9E982:                           ; CODE XREF: memmove+24Ej
  249.                 cmp     rdx, 0FFFFFFFFFFFFF000h
  250.                 ja      short loc_78E9E940
  251.  
  252. loc_78E9E98B:                           ; CODE XREF: memmove+324j
  253.                 mov     eax, 20h
  254.  
  255. loc_78E9E990:                           ; CODE XREF: memmove+2B2j
  256.                 sub     rcx, 80h
  257.                 prefetchnta byte ptr [rdx+rcx]
  258.                 prefetchnta byte ptr [rdx+rcx+40h]
  259.                 dec     eax
  260.                 jnz     short loc_78E9E990
  261.                 add     rcx, 1000h
  262.                 mov     eax, 40h
  263.  
  264. loc_78E9E9B0:                           ; CODE XREF: memmove+314j
  265.                 mov     r9, [rdx+rcx-8]
  266.                 mov     r10, [rdx+rcx-10h]
  267.                 movnti  qword ptr [rcx-8], r9
  268.                 movnti  qword ptr [rcx-10h], r10
  269.                 mov     r9, [rdx+rcx-18h]
  270.                 mov     r10, [rdx+rcx-20h]
  271.                 movnti  qword ptr [rcx-18h], r9
  272.                 movnti  qword ptr [rcx-20h], r10
  273.                 mov     r9, [rdx+rcx-28h]
  274.                 mov     r10, [rdx+rcx-30h]
  275.                 sub     rcx, 40h
  276.                 movnti  qword ptr [rcx+18h], r9
  277.                 movnti  qword ptr [rcx+10h], r10
  278.                 mov     r9, [rdx+rcx+8]
  279.                 mov     r10, [rdx+rcx]
  280.                 dec     eax
  281.                 movnti  qword ptr [rcx+8], r9
  282.                 movnti  qword ptr [rcx], r10
  283.                 jnz     short loc_78E9E9B0
  284.                 sub     r8, 1000h
  285.                 cmp     r8, 1000h
  286.                 jnb     loc_78E9E98B
  287.                 lock or byte ptr [rsp+0], 0
  288.                 jmp     loc_78E9E8DE
  289. memmove         endp
  290.  
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

FlierMate

  • Guest
Re: WinAPI - examples - post 2
« Reply #11 on: March 02, 2021, 02:55:34 pm »
Thanks @lucamar for your additional information. 32-bit Windows still allows 16-bit DOS programs to run. I do not know about Windows 2000 and XP, but Windows 10 32-bit needs NTVDM (Virtual DOS Machine) feature turned on to run legacy apps.

Thanks @440bx for the lengthy information. No wonder I could not find the function in ReactOS since it is not available in 32-bit.
The ASM dump is interesting, I thought I would expect CPU instruction like:
Code: ASM  [Select][+][-]
  1. rep stosb
But I did not notice any of this. My old DOS program actually use the code above to copy image data to A000:0 video memory.
You are more competent (in study of operating system and portable executable) than what I initially thought.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
Re: WinAPI - examples - post 2
« Reply #12 on: March 03, 2021, 09:04:09 am »
The ASM dump is interesting, I thought I would expect CPU instruction like:
Code: ASM  [Select][+][-]
  1. rep stosb
But I did not notice any of this. My old DOS program actually use the code above to copy image data to A000:0 video memory.

That's because rep stosb is slow (at least compared with other instructions). There might not be much difference with small amount of data, but for large sizes it's noticeable. Also it does not handle the case of overlapping source and target areas.

Take a look for example at FPC's Move implementation (you can find them in the CPU specific directories of the RTL, e.g. for x86_64 it would be $fpcdir\rtl\x86_64\x86_64.inc).

FlierMate

  • Guest
Re: WinAPI - examples - post 2
« Reply #13 on: March 04, 2021, 01:16:44 pm »
Take a look for example at FPC's Move implementation (you can find them in the CPU specific directories of the RTL, e.g. for x86_64 it would be $fpcdir\rtl\x86_64\x86_64.inc).

I am still downloading it, it is quite thrilling knowing I would be looking at source of my favorite compiler.

That's because rep stosb is slow (at least compared with other instructions). There might not be much difference with small amount of data, but for large sizes it's noticeable. Also it does not handle the case of overlapping source and target areas.

Do they still use "CPU cycles" per instruction to find out the speed?  :-\

 

TinyPortal © 2005-2018