Tag: winapi

Entries for tag "winapi", ordered from most recent. Entry count: 18.

Warning! Some information on this page is older than 5 years now. I keep it for reference, but it probably doesn't reflect my current knowledge and beliefs.

Pages: 1 2 3 >

# When QueryPerformanceCounter call takes long time

13:06
Sun
03
Dec 2017

QueryPerformanceCounter function is all about measuring time and profiling performance, so I wasn't able to formulate right Google query to find a solution to the problem I had - call to QueryPerformanceCounter function itself taking too much time. Below I describe what I eventually found out.

It all started from hardware failure. My motherboard stopped working, so I needed to buy a new one (ASRock X370 Killer SLI). I know that normally changing motherboard requires reinstalling Windows, but I tried not to do it. The system didn't want to boot, so I booted the PC using pendrive with Windows installer and launched the repair function. It helped - after that Windows was able to start and everything seemed to work... until I launched the program that I develop on that machine. It was running painfully slow.

I tried different things to find out what is happening. Input/output to hard drive or network was not an issue. GPU performance was also OK. It seemed that the app is just doing its calculations slowly, like the CPU was very slow. I double-checked actual CPU and RAM frequency, but it was OK. Finally I launched sampling profiler (the one embedded in Visual Studio - command: Analyze > Performance Profiler). This way I found that most of the time is spent in function QueryPerformanceCounter.

This WinAPI function is the recommended way to obtain a timestamp in Windows. It's very precise, monotonic, safe to use on multiple cores and threads, it has stable frequency independent of CPU power management or Turbo Boost... It's just great, but in order to meet all these requirements, Windows may use different methods to implement it, as described in article Acquiring high-resolution time stamps. Some of them are fast (just reading TSC register), others are slow (require system call - transition to kernel mode).

I wrote a simple C++ program that tests how long it takes to execute QueryPerformanceCounter function. You can see the code here: QueryPerformanceCounterTest.cpp and download 64-bit binary here: QueryPerformanceCounterTest.zip. Running this test on two different machines gave following results:

CPU: Intel Core i7-6700K, Motherboard: GIGABYTE Z170-HD3-CF:

> QueryPerformanceCounterTest.exe 1000000000
Executing QueryPerformanceCounter x 1000000000...
According to GetTickCount64 it took 0:00:11.312 (11.312 ns per call)
According to QueryPerformanceCounter it took 0:00:11.314 (11.314 ns per call)

CPU: AMD Ryzen 7 1700X, Motherboard: ASRock X370 Killer SLI (changed from different model without system reinstall):

> QueryPerformanceCounterTest.exe 10000000
Executing QueryPerformanceCounter x 10000000...
According to GetTickCount64 it took 0:00:24.906 (2490.6 ns per call)
According to QueryPerformanceCounter it took 0:00:24.911 (2491.1 ns per call)

As you can see, the function takes 11 nanoseconds on first platform and 2.49 microsenonds (220 times more!) on the second one. This was the cause of slowness of my program. The program calls this function many times.

I tried to fix it and somehow convince Windows to use the fast implementation. I uninstalled and reinstalled motherboard drivers - the latest ones downloaded from manufacturer website. I upgraded and downgraded BIOS to different versions. I booted the system from Windows installation media and "repaired" it again. I restored default settings in UEFI/BIOS and tried to change "ACPI HPET Table" option there to Disabled/Enabled/Auto. Nothing worked. Finally I restored Windows to factory settings (Settings > Update & Security > Recovery > Reset this PC). This solved my problem, but unfortunately it's like reinstalling Windows from scratch - now I need to install and configure all the apps again. After that the function takes 22 ns on this machine.

My conclusions from this "adventure" are twofold:

  1. It is valid for function QueryPerformanceCounter to execute slowly on some platforms, like for 2.5 microseconds. If you call it just once per rendering frame then it doesn't matter, but you shouldn't profile every small portion of your code with it, calling it millions of times.
  2. Windows 10 still requires reinstallation when changing motherboard. Otherwise, even if it seems to work, you may experience strange issues like this one.

Update 2017-12-11: A colleague told me that enabling/disabling HPET using "bcdedit" system command could possibly help for that issue.

Comments | #winapi #optimization #hardware #windows Share

# Lost clicks and key presses on low FPS

13:34
Sun
22
Oct 2017

There is a problem with handling input from mouse and keyboard in games and other interactive applications that I just solved. I would like to share my code for the solution. When your app uses a loop that constantly calculates and renders frames, like games usually do, it may seem natural to just read current state of every mouse and keyboard key (whether it's down or up) on each frame. You may then caculate derived information, like whether a button has just been pressed on released, by comparing new state to the state from previous frame. This is how Dear ImGui library works. So first solution could look like this:

void UpdateFrame()
{
    // Fill ImGui::GetIO().DeltaTime, KeyCtrl, KeyShift, KeyAlt etc.
    ImGui::GetIO().MouseDown[0] = (GetKeyState(VK_LBUTTON) & 0x8000) != 0;
    ImGui::GetIO().MouseDown[1] = (GetKeyState(VK_RBUTTON) & 0x8000) != 0;
    ImGui::GetIO().MouseDown[2] = (GetKeyState(VK_MBUTTON) & 0x8000) != 0;
    for(uint32_t i = 0; i < 512; ++i)
        ImGui::GetIO().KeysDown[i] = (GetKeyState(i) & 0x8000) != 0;
    
    ImGui::NewFrame();
    
    if(ImGui::IsKeyPressed('A'))
        // Do something...
}

There is one problem with this approach. If user presses and releases a key for a very short time, so that both press and release happens between two frame, it will go unnoticed. This is very annoying. It happens especially when:

First step towards solving this is to react to "real" events that are sent by the operating system:

Read full entry > | Comments | #gui #winapi #windows Share

# Handling Multiple Mice with Raw Input

23:29
Thu
21
Mar 2013

When you connect second USB mouse to your computer, you don't have second cursor to move on the screen and click on things. Instead you can move and click the single cursor with both mice. What if you want to distinguish messages from multiple mice in your program? I found the solution here. I downloaded and looked at the source code of MouseParty.zip linked from this page.

Handling multiple mice is possible using part of WinAPI called Raw Input. If you have <Windows.h> included, have your WinAPI window and message loop, you only need to initialize Raw Input like this:

RAWINPUTDEVICE device;
device.usUsagePage = 0x01;
device.usUsage = 0x02;
device.dwFlags = 0;
device.hwndTarget = 0;
RegisterRawInputDevices(&device, 1, sizeof device);

You then start to receive WM_INPUT message, which should be handled this way:

case WM_INPUT:
  OnRawInput(
    GET_RAWINPUT_CODE_WPARAM(wParam) == RIM_INPUT,
    (HRAWINPUT)lParam);
  // Must call DefWindowProc!
  break;

Read full entry > | Comments | #winapi Share

# Easiest Way to Generate a Bitmap

15:35
Wed
19
Oct 2011

I wanted to visualize results of some mathematical computations so I wondered what is the easiest way to generate and then show or save a bitmap? I considered Scilab, PHP with GD library, C++ with WinAPI GDI, C++ with some library that have image file formats support like FreeImage... Finally I've came up with the following solution, using only C++ and WinAPI to fill appropriate data structures and save the image as 24-bit BMP file.

// Width and height of the bitmap
unsigned size_x = 1280, size_y = 720;
// Rows top-down,
// for each row pixels from left to right,
// for each pixel components B, G, R = 0..255.
unsigned data_size = size_x * size_y * 3;
unsigned char *data = new unsigned char[data_size];

// Here fill the data, for example:
for (unsigned y = 0, i = 0; y < size_y; ++y) {
  for (unsigned x = 0; x < size_x; ++x) {
    data[i++] = 255; // G
    data[i++] = 255; // B
    data[i++] = 255; // R
  }
}

// Prepare data structures
DWORD data_offset = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
DWORD file_size = data_offset + data_size;
BITMAPFILEHEADER file_header = {
  0x4D42, // bfType = "BM"
  file_size, // bfSize
  0, 0, // bfReserved1, bfReserved2
  data_offset, // bfOffBits
};
BITMAPINFOHEADER info_header = {
  sizeof(BITMAPINFOHEADER), // biSize
  (LONG)size_x, -(LONG)size_y, // biWidth, biHeight
  1, // biPlanes
  24, // biBitCount
  BI_RGB, // biCompression
  0, // biSizeImage
  72, 72, // biXPelsPerMeter, biYPelsPerMeter
  0, 0, // biClrUsed, biClrImportant
};

// Save file
FILE *file = fopen("file_name.bmp", "wb");
fwrite(&file_header, sizeof(file_header), 1, file);
fwrite(&info_header, sizeof(info_header), 1, file);
fwrite(&data[0], 1, data_size, file);
fclose(file);

// Finalize
delete [] data;

Comments | #rendering #winapi #c++ Share

# Handling Ctrl+C in Windows Console Application

09:23
Wed
28
Sep 2011

Just a small code snippet: Let's say you write a console application in native C++ for Windows. Closing the console by pressing Ctrl+C, Ctrl+Break or clicking on close window button [X] kills the process. Is there any way to handle such event and close the program gracefully? The answer is calling SetConsoleCtrlHandler() WinAPI function and implementing your own HandlerRoutine callback function. The template looks like this:

// Handler function will be called on separate thread!
static BOOL WINAPI console_ctrl_handler(DWORD dwCtrlType)
{
  switch (dwCtrlType)
  {
  case CTRL_C_EVENT: // Ctrl+C
    break;
  case CTRL_BREAK_EVENT: // Ctrl+Break
    break;
  case CTRL_CLOSE_EVENT: // Closing the console window
    break;
  case CTRL_LOGOFF_EVENT: // User logs off. Passed only to services!
    break;
  case CTRL_SHUTDOWN_EVENT: // System is shutting down. Passed only to services!
    break;
  }

  // Return TRUE if handled this message, further handler functions won't be called.
  // Return FALSE to pass this message to further handlers until default handler calls ExitProcess().
  return FALSE;
}

int main(int argc, char **argv)
{
  SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
  ...
}

If your program performs some loop and you want the user to be able to break it by closing the console or pressing Ctrl+C, you can solve it this way:

static volatile bool g_exit = false;

static BOOL WINAPI console_ctrl_handler(DWORD dwCtrlType)
{
  g_exit = true;
  return TRUE;
}

int main(int argc, char **argv)
{
  SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
  initialize();
  while (!g_exit)
    do_a_piece_of_work();
  finalize();
}

Comments | #windows #winapi #c++ Share

# Generating LIB File for DLL Library

22:09
Tue
04
Jan 2011

I've been recently trying to use libVLC - functionality of great, codec-less VLC media player enclosed in form of DLL library. By the way I've came across a great article: GenerateLibFromDll and now I know how to generate LIB file for any DLL library! Here is detailed description of the problem:

When you have a DLL library you want to use in your C++ code, you may do it dynamically by using LoadLibrary and GetProcAddress functions from WinAPI, but it's more convenient to do it statically. But it's not enough to just #include signatures of library functions and use them in your project. You also need to link with some LIB file, even if the file is not a real static library with compiled code, but only a few-kilobyte-long list of imported functions. I believe that's just another flaw of C++ language, because other languages like for example C# don't need this even when importing functions from native DLL libraries.

If you have some SDK prepared for Visual C++ or compile the library by yourself, you also get the LIB file next to DLL. But if you have only the library, that article shows following steps to generate matching LIB:

1. From Start menu run "Visual Studio Command Prompt".

2. Execute command:

dumpbin /exports DLL_FILE.dll > DEF_FILE.def

This command prints some information about given DLL library in textual form to its standard output. We redirect it to a text file with DEF extension. But to make it real DEF file, we need to edit it.

3. Open DEF_FILE.def in some text editor and edit it to contain only the names of exported functions in form of:

EXPORTS
function_1_name
function_2_name
function_3_name
...

4. From the Visual Studio Command Prompt, execute another command:

lib /def:DEF_FILE.def /out:LIB_FILE.lib /machine:x86

And there you have it! The so much required LIB file generated from DLL library. You only need signatures of these functions with proper parameters and return values declared in some H header file and you can successfully use your DLL by linking with LIB file created by yourself :)

Comments | #visual studio #c++ #windows #winapi Share

# Coding Windows Services in C++

18:31
Fri
01
Oct 2010

Services in Windows are like daemons in Linux - resident programs that work in background. I've recently learned how to code them in C++ using WinAPI. Here is a quick tutorial about this:

All the documentation you need to develop services can be found in MSDN Library. If you have it offline, go to: Win32 and COM Development / System Services / DLLs, Processes and Threads / SDK Documentation / DLLs, Processed, and Threads / Services. You can also read it online HERE. I talk only about native C and C++ code here, but services can also be written in .NET.

What are pros and cons of services, comparing to normal applications? Service can be automatically started with the system and work all the time, no matter if any user logs on and off. It can have extensive priviledges to access files on hard disk and the like, no matter what limitations do the logged-in user have. But service cannot interact directly with the user - it cannot show console or any window. So the only way for a service to do any input/output is to read some configuration files, write some log files or to communicate with some other client process ran by the user, e.g. via TCP socket connected to "localhost".

Service is written as a console application that uses special WinAPI functions to communicate with so called SCM - Service Control Manager. Example entry point routine looks like this:

// Standard console application entry point.
int main(int argc, char **argv)
{
    SERVICE_TABLE_ENTRY serviceTable[] = {
        { _T(""), &ServiceMain },
        { NULL, NULL }
    };
       
    if (StartServiceCtrlDispatcher(serviceTable))
        return 0;
    else if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
        return -1; // Program not started as a service.
    else
        return -2; // Other error.
}

StartServiceCtrlDispatcher is the first service-related function used here. It needs an array because a process can implement multiple different services, but I show only single-service process here. The function blocks for the entire execution time of working service and fails if program was run as normal application, not as a service. While service is working, a callback function is being executed, which I called ServiceMain here. It should initialize service and then execute all the code in loop until system wants to stop the service. You can also exit the function and thus stop the service at any time if you want (e.g. if some critical error occured).

// Main function to be executed as entire service code.
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
    // Must be called at start.
    g_ServiceStatusHandle = RegisterServiceCtrlHandlerEx(_T("SERVICE NAME"), &HandlerEx, NULL);
   
    // Startup code.
    ReportStatus(SERVICE_START_PENDING);
    g_StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    /* Here initialize service...
    Load configuration, acquire resources etc. */
    ReportStatus(SERVICE_RUNNING);

    /* Main service code
    Loop, do some work, block if nothing to do,
    wait or poll for g_StopEvent... */
    while (WaitForSingleObject(g_StopEvent, 3000) != WAIT_OBJECT_0)
    {
        // This sample service does "BEEP!" every 3 seconds.
        Beep(1000, 100);
    }

    ReportStatus(SERVICE_STOP_PENDING);
    /* Here finalize service...
    Save all unsaved data etc., but do it quickly.
    If g_SystemShutdown, you can skip freeing memory etc. */
    CloseHandle(g_StopEvent);
    ReportStatus(SERVICE_STOPPED);
}

RegisterServiceCtrlHandlerEx is a function that must be called first to register your application as a service, pass its name and a pointer to your control event handler function. Then you do some initialization, execute main service code in a loop and after it's time to stop it, do the cleanup and exit.

Service should report its state to the SCM with SetServiceStatus function. It can be called at any time and from any thread and informs the system about if your service is stopped, running, starting, stopping, paused etc. This function takes quite sophisticated SERVICE_STATUS structure, but I believe it can be simplified to three main cases which I enclosed in the following functions: ReportStatus reports basic status like SERVICE_STOPPED, SERVICE_RUNNING, SERVICE_START_PENDING or SERVICE_STOP_PENDING.

SERVICE_STATUS_HANDLE g_ServiceStatusHandle; 
HANDLE g_StopEvent;
DWORD g_CurrentState = 0;
bool g_SystemShutdown = false;

void ReportStatus(DWORD state)
{
    g_CurrentState = state;
    SERVICE_STATUS serviceStatus = {
        SERVICE_WIN32_OWN_PROCESS,
        g_CurrentState,
        state == SERVICE_START_PENDING ? 0 : SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN,
        NO_ERROR,
        0,
        0,
        0,
    };
    SetServiceStatus(g_ServiceStatusHandle, &serviceStatus);
}

Third member of the SERVICE_STATUS structure - dwControlsAccepted - indicates which events will be accepted by the service after this call. I want to accept events informing about system shutdown and allow user to stop the service. I could also pass SERVICE_ACCEPT_PAUSE_CONTINUE here, which means I supported pausing and resuming the service.

ReportProgressStatus function reports service status during initialization and finalization - SERVICE_START_PENDING, SERVICE_STOP_PENDING, SERVICE_CONTINUE_PENDING, SERVICE_PAUSE_PENDING. I don't actually use it, but if the startup or shutdown of your service takes a lot of time, you should periodically report progress with this function. CheckPoint is simply a counter that should be incremented with each call, telling that service is making some progress. WaitHint is an estimated time it will take to finish initialization, finalization or to perform its next step. By default, system waits about 30 seconds for your service to start or stop and you should not exceed that without a good reason.

void ReportProgressStatus(DWORD state, DWORD checkPoint, DWORD waitHint)
{
    g_CurrentState = state;
    SERVICE_STATUS serviceStatus = {
        SERVICE_WIN32_OWN_PROCESS,
        g_CurrentState,
        state == SERVICE_START_PENDING ? 0 : SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN,
        NO_ERROR,
        0,
        checkPoint,
        waitHint,
    };
    SetServiceStatus(g_ServiceStatusHandle, &serviceStatus);
}

Finally, there is a way for a service to shutdown and inform the system that some critical error occured. To do this, report SERVICE_STOPPED and pass error code. The code will be saved along with information about service failture to the system event log.

void ReportErrorStatus(DWORD errorCode)
{
    g_CurrentState = SERVICE_STOPPED;
    SERVICE_STATUS serviceStatus = {
        SERVICE_WIN32_OWN_PROCESS,
        g_CurrentState,
        0,
        ERROR_SERVICE_SPECIFIC_ERROR,
        errorCode,
        0,
        0,
    };
    SetServiceStatus(g_ServiceStatusHandle, &serviceStatus);
}

HandlerEx is a function to handle events sent by the system to control your service - stop it, pause, inform about the system shutdown or simply query for current status. You must always call SetServiceStatus in this function. It can be executed in different thread, so you must synchronize it with the code in ServiceMain. I do this with g_StopEvent - an event that will be set when the service should exit.

// Handler for service control events.
DWORD WINAPI HandlerEx(DWORD control, DWORD eventType, void *eventData, void *context)
{
    switch (control)
    {
    // Entrie system is shutting down.
    case SERVICE_CONTROL_SHUTDOWN:
        g_SystemShutdown = true;
        // continue...
    // Service is being stopped.
    case SERVICE_CONTROL_STOP:
        ReportStatus(SERVICE_STOP_PENDING);
        SetEvent(g_StopEvent);
        break;
    // Ignoring all other events, but we must always report service status.
    default:
        ReportStatus(g_CurrentState);
        break;
    }
    return NO_ERROR;
}

That's all the code I wanted to show. Now, because service cannot be run as normal program, you must learn how to install and uninstall it. Fortunately there is a simple command line program for this distributed with Windows - sc. To install your service, enter following command (exactly like this, with "binPath=" SPACE "PATH"):

sc create SERVICE_NAME binPath= FULL_PATH_TO_EXE_FILE

To uninstall it:

sc delete SERVICE_NAME

To control your service - start it, stop it or query its status - use commands:

sc start SERVICE_NAME
sc stop SERVICE_NAME
sc query SERVICE_NAME

Or simply run Administrative Tools / Services (another way to access it is Start / Run / "services.msc").

Two kinds of command line arguments can be passed to a service. First are argc, argv parameters taken by main function. They come from a command line fixed during installation of the service. Second are argc, argv arguments taken by ServiceMain function. They are different - argv[0] is the service name and the rest are arguments that you passed as additional parameters when calling "sc start" command.

Of course there is more to be told on this subject. Service can depend on some other services, can be automatically started with the system or only on demand, can have priviledges of a selected user or one of standard ones, like "LocalSystem" (biggest priviledges on local system, the default), "LocalService" or "NetworkService". See MSDN Library for details.

Comments | #c++ #windows #winapi Share

# How to Disable Redrawing of a Control

18:43
Thu
18
Mar 2010

When coding Windows application with GUI, there is an issue about how long does it take to add lots of items (like hundreds or thousands) into a list view or tree view control. It is caused by redrawing the control after each operation. I've seen this annoying effect in may programs, including some serious, commercial ones. Apparently many programmers don't know there is a simple solution. But first a bit of background...

When coding games, we constantly spin inside a big loop and redraw whole screen every frame. Calculations are separated from rendering so we can, for example, build a list with thousands of items in the computation function and the visible part of the list will start being rendered since the first rendering function call after that. When coding windowed applications, nothing new is drawn onto the screen unless needed. We have to manually do it and we can call redrawing function any time. So how should a list control be refreshed when we add an item into it? It is done automatically after each insert, which is a good solution... unless we want to add hundreds of them.

So GUI library developers provide a functionality to temporarily disable redrawing of a control.

Comments | #.net #mfc #wxwidgets #winapi #gui Share

Pages: 1 2 3 >

STAT NO AD
[Stat] [STAT NO AD] [Download] [Dropbox] [pub] [Mirror] [Privacy policy]
Copyright © 2004-2018