In Using the Windows Headers, Microsoft claim that _WIN32_WINNT and NTDDI_VERSION can be used to prevent defining API functions for newer versions of Windows. However, this does not seem to be universally true.
For example, CancelSynchronousIo requires Vista or later, but it is not guarded at all in the two versions of the windows SDK that I have (v6.0 and v7.1).
WINBASEAPI
BOOL
WINAPI
CancelIoEx(
__in HANDLE hFile,
__in_opt LPOVERLAPPED lpOverlapped
);
Meanwhile, GetVolumeInformationByHandleW, which also requires Vista, is guarded as you might expect:
#if(_WIN32_WINNT >= 0x0600)
WINBASEAPI
BOOL
WINAPI
GetVolumeInformationByHandleW(
__in HANDLE hFile,
__out_ecount_opt(nVolumeNameSize) LPWSTR lpVolumeNameBuffer,
__in DWORD nVolumeNameSize,
__out_opt LPDWORD lpVolumeSerialNumber,
__out_opt LPDWORD lpMaximumComponentLength,
__out_opt LPDWORD lpFileSystemFlags,
__out_ecount_opt(nFileSystemNameSize) LPWSTR lpFileSystemNameBuffer,
__in DWORD nFileSystemNameSize
);
#endif /* _WIN32_WINNT >= 0x0600 */
Is this sort of thing just a bug? Are _WIN32_WINT guards useless? Can anyone recommend a reliable way to determine which version of Windows introduced which API functions?
Edited to add:
Here is a test. foo.h contains:
#include <windows.h>
Then run:
cl /E /D_WIN32_WINNT=0x0501 /DNTDDI_VERSION=0x05010000 foo.h | grep CancelSynchronousIo
My expectation is that I'd get no output, but instead CancelSynchronousIo is defined.
It's a bug. Reference examples are here and here. Some secondary evidence that the Longhorn project was indeed a very troubled one. The Windows team doesn't take feedback like DevDiv does, hard to get bugs fixed. You can leave an annotation at the bottom of the MSDN Library page.
Related
I'm trying to invoke ZwCreateThread(). But since it is a undocumented function I don't know how to do it. The 3rd, 5th, 6th and 7th argument of the function?
How to initialize those structures to use them in ZwCreateThread()?
The question is a loaded one
I don't fully agree with the assessment by Basile in the comments that - if something is undocumented - it should not be used. But it requires extra caution for sure.
There is also a relevant bit of information missing from your question: kernel or user mode?!
Resources
I cannot answer regarding fasm, but if you know how to read C function prototypes and make those work for you, you can use one of the following resources to find the prototypes:
undocumented.ntinternals.net
the phnt offspring of the Process Hacker (mind the license!)
ReactOS tries to be a fairly faithful functional clone of Windows (the target version has been adjusted over the years)
The desired information is part of the NDK inside psfuncs.h
The Windows Research Kernel and its documentation have leaked and were available in several shapes and forms all over the web (IIRC this was based on Windows 2003 Server)
Microsoft documents some functions and structs as part of their Windows Driver Kits (WDKs, formerly Device Driver Kits [DDKs])
winternl.h is one of the headers
"Windows NT/2000 Native API Reference" by Gary Nebbett
"Undocumented Windows 2000 Secrets" by Sven B. Schreiber; IIRC the author made this available on his website as several PDFs some years ago
"Undocumented Windows NT" by Prasad Dabak, Sandeep Phadke, and Milind Borate
The syscall tables (j00ru/windows-syscalls) as a reference of sorts for availability of functions from user mode
For structs as found from the PDBs (debugging symbols) made available by Microsoft: Vergilius Project
Yet again for structs, but more useful for user mode: Terminus Project by ReWolf
Windows NT, Secret APIs and the Consequences by Bruce Ediger
To a lesser extent the "Windows Internals" books from Microsoft Press
A code search or GitHub/GitLab/etc search for some of your desired function names or related functions
E.g. in the source code to several debuggers or other very low-level tools, to binary instrumentation frameworks etc ...
Books and resources for related topics such as sandboxes, rootkits, bootkits, malware ...
Useful knowledge
ZwCreateThread and NtCreateThread are identical in user mode (you can even verify this by using dumpbin on ntdll.dll and checking the RVA of the two exports. This is true for most (if not all) Zw* and Nt* functions
This means their prototype is identical!
In kernel mode they differ, one of them does more checking and is supposed to receive calls via the SSDT from user mode, the other is supposed to be called from kernel mode.
The identical prototype notion also holds true here
... let's try to answer it
Up front: if what you are trying to achieve is to create a user mode thread, in all likelihood RtlCreateUserThread() is more likely what you are looking for (for reference phnt)!
The prototype for ZwCreateThread is as follows:
// source: ntzwapi.h from https://github.com/processhacker/phnt
NTSYSCALLAPI
NTSTATUS
NTAPI
ZwCreateThread(
_Out_ PHANDLE ThreadHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ HANDLE ProcessHandle,
_Out_ PCLIENT_ID ClientId,
_In_ PCONTEXT ThreadContext,
_In_ PINITIAL_TEB InitialTeb,
_In_ BOOLEAN CreateSuspended
);
// for reference, Nebbett gives the prototype as:
NTSYSAPI
NTSTATUS
NTAPI
ZwCreateThread(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN HANDLE ProcessHandle,
OUT PCLIENT_ID ClientId,
IN PCONTEXT ThreadContext,
IN PUSER_STACK UserStack,
IN BOOLEAN CreateSuspended
);
You probably noticed the difference in the parameter 7 (starting at 1) immediately: PUSER_STACK vs. PINITIAL_TEB. TEB stands for Thread Environment Block and is the extension of the TIB (IIRC: Thread Information Block). Compare Nebbett's take on the USER_STACK struct:
typedef struct _USER_STACK {
PVOID FixedStackBase;
PVOID FixedStackLimit;
PVOID ExpandableStackBase;
PVOID ExpandableStackLimit;
PVOID ExpandableStackBottom;
} USER_STACK, *PUSER_STACK;
... with the INITIAL_TEB from undocumented.ntinternals.net you will notice they're the same (also for reference phnt). Nebbett took a guess at the name at the time of his writing. But this right there is the reason why Basile cautions not to use undocumented functions. You have to put in your own research and can't blindly rely on others' research. Also you should apply a very defensive coding style when using those functions.
Either way, Nebbett lists CreateThread() and CreateRemoteThread() as related Windows APIs. The latter is obviously a superset of the former and ZwCreateThread() uses ProcessHandle for the target process. It's always worthwhile looking for and looking at related Windows APIs.
3rd parameter: _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes
The _In_opt (see SAL) tells you, that you may pass a NULL pointer here. But if you insist on passing the object attributes and know what to put in them: InitializeObjectAttributes() - a macro - is there to help.
5th parameter: _Out_ PCLIENT_ID ClientId
The _Out_ tells you that you supply the space for this info to be filled. The CLIENT_ID combines process and thread ID into a struct. The struct can be found in the headers of the WDKs/DDKs (e.g. wdm.h or ntddk.h) and looks like this in C:
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID;
6th parameter: _In_ PCONTEXT ThreadContext
The CONTEXT is indeed a documented struct and used in official APIs such as SetThreadContext(). Its definition depends on the target architecture, but can be found in official MS headers.
This struct also plays a big role in exception handling, e.g. when resuming execution after an exception.
For ZwCreateThread() this defines the initial state of the thread, especially the initial address of the instruction pointer and the initial CPU register states (which explains why it depends on the target architecture).
7th parameter: _In_ PINITIAL_TEB InitialTeb
By now you should have an idea that you need to supply the space and initial values for this struct as well.
Conclusion
And this complicated "having to know and fill in all details" explains why in all likelihood you want to use:
typedef NTSTATUS (NTAPI *PUSER_THREAD_START_ROUTINE)(
_In_ PVOID ThreadParameter
);
NTSYSAPI
NTSTATUS
NTAPI
RtlCreateUserThread(
_In_ HANDLE Process,
_In_opt_ PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,
_In_ BOOLEAN CreateSuspended,
_In_opt_ ULONG ZeroBits,
_In_opt_ SIZE_T MaximumStackSize,
_In_opt_ SIZE_T CommittedStackSize,
_In_ PUSER_THREAD_START_ROUTINE StartAddress,
_In_opt_ PVOID Parameter,
_Out_opt_ PHANDLE Thread,
_Out_opt_ PCLIENT_ID ClientId
);
// again taken from phnt
This is much closer to CreateRemoteThreadEx and similar APIs. You don't have to care about the initial CONTEXT and don't have to deal with OBJECT_ATTRIBUTES or INITIAL_TEB.
I have making an attempt at writing my first program in Visual Studio, however am being troubled by an error.
It says: -
Error 3 error LNK2019: unresolved external symbol _wWinMain#16 referenced in function ___tmainCRTStartup
E:\Documents\Programming\Software Development\Microsoft Development\Microsoft Development\MSVCRTD.lib(wcrtexew.obj)
Microsoft Development
On researching I found similar errors, but none have helped me solve the problem.
I have changed the entry point to
wWinMainCRTStartup
the character set to Unicode
the subsystem to console. The project is a win32 application. The code is as follows: -
#include <windows.h>
#include <stdio.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, "Hello World!", "Note", 1/*MB_OK*/);
printf("nCmdShow = %d\n", nCmdShow);
return 0;
}
How do I fix this issue?
P.S. I am using Visual Studio Ultimate 2013
For a Unicode build your code needs to be more like this:
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, L"Hello World!", L"Note", 1/*MB_OK*/);
printf(L"nCmdShow = %d\n", nCmdShow);
return 0;
}
At least by default this will be set to use the Windows subsystem (because the entry point is named a variant of WinMain). You can force that to the console subsystem (-subsystem:console flag to the linker) or get it to happen by default by changing the entry point to a variant of main instead:
int wmain(int argc, wchar_t **argv) { // ...
Obviously you won't be able to print nCmdShow using this though (not that it really means anything in a console program). For that matter, since you're not using the command line arguments anyway, you can simplify this somewhat to:
int wmain(){ // ....
Actually, nCmdShow is basically obsolete even for windowed programs. The first time a windowed program calls ShowWindow, it normally passes nCmdShow as the parameter. Windows, in turn, ignores the value passed in the first call to ShowWindow, and instead uses the value from the process' STARTUPINFO structure. Only in subsequent calls to ShowWindow is the parameter used (and for these subsequent calls, you're not supposed to pass nCmdShow either--you're supposed to pass one of the defined constants such as SW_SHOWNORMAL).
Reference: MSDN entry for ShowWindow
A Win32 application starts at WinMain. A console application starts at main. Your question implies you have a confused mixture of the two.
Just use the File, New, Project menu command to let Visual Studio build a skeleton of the type of application you have in mind.
With the code below, the console is hidden BUT it appears for about 1 second.
How can I completely hide the console ?
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <iostream>
using namespace std;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow){
HWND hWnd = GetConsoleWindow();
ShowWindow( hWnd, SW_HIDE );
MessageBox(NULL, TEXT("Hello!"), TEXT("yuhuuu"), 0);
return 0;
}
Something is weird with your compiler settings. (You did not specify your compiler so I'm assuming MSVC)
The WinMain entry point function from your example is used by GUI applications (Linker switch /SUBSYSTEM:WINDOWS) and those applications don't get a console unless you call AllocConsole.
If you link with /SUBSYSTEM:CONSOLE then Windows will create a console for the process before your code is executed but a normal entry point for those applications is the plain old main function.
Are you forcing the entry point with the /ENTRY switch? Either way, make sure the /SUBSYSTEM switch and the entry point function definition are compatible and match the type of application you want to create (GUI or console)
I'm trying to help a colleague with some code in a client side extension. Since adding in a call to the callback, the function seems to complete ok, but an event in the Windows Event log complains about an access violation whilst processing the group policy object.
After removing existing code, with just the added call to the callback, it still reports this access violation.
Can you please help identify what we might be missing?
//
// Entry point for processing group policy objects.
//
// For full details, see http://msdn.microsoft.com/en- us/library/windows/desktop/aa374383(v=vs.85).aspx.
//
extern "C" DWORD CALLBACK ProcessGroupPolicyEx (
__in DWORD dwFlags,
__in HANDLE hToken,
__in HKEY hKeyRoot,
__in PGROUP_POLICY_OBJECT pDeletedGPOList,
__in PGROUP_POLICY_OBJECT pChangedGPOList,
__in ASYNCCOMPLETIONHANDLE pHandle,
__in BOOL *pbAbort,
__in PFNSTATUSMESSAGECALLBACK pStatusCallback,
__in IWbemServices *pWbemServices,
__out HRESULT *pRsopStatus)
{
if(pStatusCallback)
pStatusCallback (FALSE, L"Aaaaargh!");
return (0);
}
This code has been tried using a static string, an array of bytes on the stack, a array of bytes that's been new'd and deliberately leaked - in case the method was taking ownership of the memory. Also been CoTaskMemAlloc'd, just in case. All produce the same problem.
The (redacted) error in the eventlog is:
Windows cannot process Group Policy Client Side Extension Exception 0xc0000005.
To make things interesting, this is just on some OS's, fully patched XP 32bit is one of the definite problems. 2008R2 works fine.
Yes - we need it to work on XP 32bit.
Other weird behaviour that may have a bearing here:
If we call this function multiple times, it fails on the 3rd call. No exception is thrown, no text is shown, none of our code after the call is executed, no additional errors in the event log. Timing is not a factor here: it happens if you call it 3 times in a row, or 3 times over 5 minutes.
This does not happen if we wrap the calls in a generic try/catch block. No exception is caught - all the text is shown. All the code is run.
We still get the error in the event log, however.
Looks like we've found the issue with this.
The problem is that the callback needs to be made with __stdcall calling convention.
By default, visual studio creates projects with the __cdecl calling convention.
If you add the /Gz flag to your project, it will use __stdcall by default. We couldn't do that, however, since we're pulling in other modules with different calling conventions.
The underlying problem is that UserEnv.h defines the callback like this:
typedef DWORD (*PFNSTATUSMESSAGECALLBACK)(__in BOOL bVerbose, __in LPWSTR lpMessage);
This is a strange definition. All other windows callbacks are defined like this:
typedef INT_PTR (CALLBACK* DLGPROC)(HWND, UINT, WPARAM, LPARAM);
That CALLBACK is important, it expands like this:
#define CALLBACK __stdcall
This means that by default, all windows callbacks are defined to use __stdcall calling conventions, except this one, for some reason.
If we create our own callback defintion:
typedef DWORD (CALLBACK *PFNSTATUSMESSAGECALLBACK_STDCALL)(__in BOOL bVerbose, __in LPWSTR lpMessage);
And assign our function pointer to it:
PFNSTATUSMESSAGECALLBACK_STDCALL pStatusCallback = (PFNSTATUSMESSAGECALLBACK_STDCALL)pRawStatusCallback;
Then we can use the pStatusCallback function pointer with the __stdcall calling convention and have things work properly.
Specifically, I want to use Point-to-point Message Queue but because I am still using legacy codes in eVC++ 4 and it only support until PocketPC 2003SE SDK, I cannot find CreateMsgQueue and friends in the headers (the port to newer VisualStudio is still in progess)
I am using the Message Queue to do IPC with apps developed with WM-6.5-DTK (VS2005).
Update:
I am using the following code (taken from msgqueue.h) to store function pointers and load CoreDLL.dll using GetProcAddress() and LoadLibrary() respectively.
HANDLE /*WINAPI*/ (*CreateMsgQueue)(LPCWSTR lpName, LPMSGQUEUEOPTIONS lpOptions);
HANDLE /*WINAPI*/ (*OpenMsgQueue)(HANDLE hSrcProc, HANDLE hMsgQ
, LPMSGQUEUEOPTIONS lpOptions);
BOOL /*WINAPI*/ (*ReadMsgQueue)(HANDLE hMsgQ,
/*__out_bcount(cbBufferSize)*/ LPVOID lpBuffer, DWORD cbBufferSize,
LPDWORD lpNumberOfBytesRead, DWORD dwTimeout, DWORD *pdwFlags);
BOOL /*WINAPI*/ (*WriteMsgQueue)(HANDLE hMsgQ, LPVOID lpBuffer, DWORD cbDataSize,
DWORD dwTimeout, DWORD dwFlags);
BOOL /*WINAPI*/ (*GetMsgQueueInfo)(HANDLE hMsgQ, LPMSGQUEUEINFO lpInfo);
BOOL /*WINAPI*/ (*CloseMsgQueue)(HANDLE hMsgQ);
Is the above code alright since I need to comment out WINAPI and __out_bcount(cbBufferSize) in order for them to compile.
As pointed out by ctacke, it is actually available on PPC2003 SDK. The Requirement in the MSDN is wrong.
Btw, the above approach seems to work fine even after commenting out WINAPI and __out_bcount(cbBufferSize)