-5

Is it possible to write winapi function prototypes in a C file

I know that it is possible, because the function prototype (CryptAcquireContextW above works to my delight

But I can't write VirtualLock prototypes, the compiler doesn't even complain about an unresolved symbol, it just reads it as a syntax error and expects ")" after the first parameter. I have a header in front of my eyes

C:\Program Files (x86)\Windows Kits\10\Include\10.0.20348.0\um

used CMAKE and tested previous compiled and executed

#ifdef WINDOWS_branching_OP_1   

#if defined(_WIN64)
#define ULONG_PTR unsigned  int64_t // __int64
#else
#define ULONG_PTR unsigned long
#endif

#define DWORD unsigned long
#define QWORD unsigned __int64
#define BYTE  unsigned char
#define BOOL  int

#define LPVOID void*

#define SIZE_T ULONG_PTR

#define HCRYPTPROV unsigned long long
#define LPCWSTR    const wchar_t*


#define WINADVAPI
#define WINAPI __stdcall

#pragma comment(lib, "advapi32.lib")


WINADVAPI BOOL WINAPI CryptAcquireContextW(
    HCRYPTPROV *phProv,
    LPCWSTR pszContainer,
    LPCWSTR pszProvider,
    DWORD dwProvType,
    DWORD dwFlags
);

WINADVAPI BOOL WINAPI CryptGenRandom(
    _In_                    HCRYPTPROV  hProv,
    _In_                    DWORD   dwLen,
    _Inout_updates_bytes_(dwLen)   BYTE    *pbBuffer
);

#define WINBASEAPI

WINBASEAPI BOOL WINAPI VirtualLock(
    _In_ LPVOID lpAddress,
    _In_ SIZE_T dwSize
    );



#endif 

there are other things that bother me:

  1. why can't we limit ourselves to function prototypes and I'll have to import the full Header windows.h or memoryapi.h for both the random number functions and the Swap protection functions
  2. why couldn't I find information on this topic, this is something exceptional, give me information and sources regardless of complexity
  3. fundamental sources on platform-independent compilation, if you think I'm doing something wrong, I can relearn without asking questions. I need to secure additional functionality in the finished project

cmake 3.30.3 x86_64
VS 2022 BuildTools

I compile static linked library in C. use inside C++/QT IDE qtcreator with main project and other with tested functional

11
  • 3
    What problem do you think you solve by avoiding #includeing the header files that provide these declarations? Commented Apr 26 at 17:37
  • 1 Why is that important to you? 2 Probably because it isn't important enough to pursue. 3 I don't understand the question. Commented Apr 26 at 17:38
  • 1
    Do you define the SAL macros as well? Commented Apr 26 at 17:40
  • 4
    Note that with MSVC you can #define WIN32_LEAN_AND_MEAN or #define WIN64_LEAN_AND_MEAN to exclude certain less commonly used Windows header files and API declarations from being included when you use windows.h. Once you start defining you own versions of DWORD etc, etc you open yourself to more possibility of error. Commented Apr 26 at 17:44
  • I understand, the error surface increases with self-definition and it is not worth getting into the inner workings of Microsoft why declare #define WIN32_LEAN_AND_MEAN if all the header lines, functions to which are not used, will not be included in the final executable file anyway Commented Apr 26 at 18:23

2 Answers 2

4

If you really, really just can't #include <windows.h>, then you can source every typedef and function from another standalone project that makes use of the pre-processor output

Create a standalone Visual Studio C++ console app. And open the default .cpp file that gets auto generated. It will look something like this:

// ConsoleApplication7.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <iostream>

int main()
{
    std::cout << "Hello World!\n";
}

Now add the windows include line at the top:

// ConsoleApplication7.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <windows.h>   // <<== ADD THIS LINE
#include <iostream>

Now turn on the pre-processor option, /P, in Visual Studio's compiler settings. You can right click on the .cpp file and select "properties" from the menu. Then in the properties dialog for this file, add the /P option

Now build the project or compile the primary .cpp file. This may result in an error since we're only pre-processing. That error can be ignored.

Open the .i file that got generated. This will have the entire pre-processor output of all of <windows.h>.

enter image description here

In the .i file, you can search for any function definition. Let's start with CryptAcquireContextW

__declspec(dllimport)
BOOL
__stdcall
CryptAcquireContextW(
            HCRYPTPROV  *phProv,
         LPCWSTR    szContainer,
         LPCWSTR    szProvider,
             DWORD       dwProvType,
             DWORD       dwFlags
    );

Of course, this has a bunch of Windows types used to build this function. So let's figure out how those are defined. Searching up in the .i file, we can find HCRYPTPROV is defined as:

typedef ULONG_PTR HCRYPTPROV;

And ULONG_PTR as:

typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;

And others as:

typedef wchar_t WCHAR;    
typedef   const WCHAR *LPCWSTR, *PCWSTR;
typedef unsigned long       DWORD;
typedef int                 BOOL;

So to completely avoid windows.h, we'll have the following declaration:

typedef unsigned __int64 ULONG_PTR, * PULONG_PTR;
typedef ULONG_PTR HCRYPTPROV;
typedef wchar_t WCHAR;
typedef   const WCHAR* LPCWSTR, * PCWSTR;
typedef unsigned long       DWORD;
typedef int                 BOOL;

__declspec(dllimport) BOOL __stdcall CryptAcquireContextW(
    HCRYPTPROV* phProv,
    LPCWSTR    szContainer,
    LPCWSTR    szProvider,
    DWORD       dwProvType,
    DWORD       dwFlags
);

Repeat for all the other functions you want to declare without a header file.

All of this is gross and seems like a lot of work. And it's only valid for the architecture we're building for. If this had been 32-bit x86 instead of 64-bit, those types will need to be sourced again, because I'm not sure if ULONG_PTR is 64-bit on all architectures. Same for the other types.

Wouldn't it just be easier to say this:

#ifdef WIN32
#include <windows.h>
#endif

And be done with it?

As for VirtualLock, it's this (re-use the typedef for ULONG_PTR above)

typedef void             *LPVOID;
typedef ULONG_PTR SIZE_T, *PSIZE_T;

__declspec(dllimport)
BOOL
__stdcall
VirtualLock(
      LPVOID lpAddress,
      SIZE_T dwSize
    );

Sign up to request clarification or add additional context in comments.

3 Comments

thanks, with your advice I will be able to expand and deploy the problem myself. I will need to find which dlimport dll is used for Virtualochk. I just need to put one question in a separate thread: why does it complain about syntax. is it just a function prototype with the specified types and name and the indication of the dll target? Is this an error in syntax evaluation and even if I specify everything I need, I will not be able to feed the compiler the prototype of the VirtualLock function
The DLL you seek is most likely kernel32.dll
Cenured Exclamation, yes indeed for working with libraries not related to QT in more suitable tools like VSCode or whatever is best suited for debugging Windows Indeed, memory calls will be near the kernel
1

Is it possible to write winapi function prototypes in a C file

A C implementation can provide headers that work magic that is not expressible in C. However, if a correct, C-expressible declaration of a function is available -- from documentation, say -- then it can be written in any C file. Such a declaration does not need to be obtained by #includeing a header.

But you should obtain declarations from their designated headers when there is one.

But I can't write VirtualLock prototypes, the compiler doesn't even complain about an unresolved symbol, it just reads it as a syntax error and expects ")" after the first parameter. I have a header in front of my eyes

... meaning, I guess, that you are copying code from the header you are looking at. This exercise is fraught, as system headers are notoriously difficult for humans to track properly. An error such as you describe tends to mean that a required semicolon or comma has been lost, or a needed macro definition is missing or incorrect. Producing such issues is among the risks of trying to pull declarations out of system headers.

If you are determined to proceed with this exercise then it might be easier to run the header through the preprocessor to find what declaration actually comes out the other side, and use that. This may end up acquiring some specificity to your particular build environment, though, so beware of that.

  1. why can't we limit ourselves to function prototypes and I'll have to import the full Header windows.h or memoryapi.h for both the random number functions and the Swap protection functions

You can (generally) write your own prototypes. You might not easily do so by extracting code from system headers. You should get library function declarations by #includeing the appropriate header.

  1. why couldn't I find information on this topic, this is something exceptional, give me information and sources regardless of complexity

On one hand, it is well known to most C programmers of sufficient skill to consider such a thing that yes, you can write and use your own function declarations for library functions.

On the other hand, most such programmers also understand that doing so is a bad idea. More code subject to your own responsibility means more work and more risk, and curating your own declarations for library function does not, generally, convey much in offsetting advantages.

  1. fundamental sources on platform-independent compilation, if you think I'm doing something wrong, I can relearn without asking questions. I need to secure additional functionality in the finished project

You seem to be asking for references to off-site resources. Such requests are off-topic here.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.