How to check the result of PrintUIEntry call - winapi

I'd like to use PrintUIEntryW (of printui.dll ) to install a printer driver on Windows system. My code looks like following (pseudo).
m = LoadLibrary(L"printui.dll");
printuientry = GetProcAddress(m, "PrintUIEntryW");
// set arg_string
printuientry(NULL, m, arg_string, SW_SHOW);
Could I check the return value of the function or something like GetLastError() to check if the desired call is successful? There seems no msdn entry for this function.
Thanks in advance.

PrintUIEntry is documented here:
Rundll32 printui.dll,PrintUIEntry
rundll32 is documented is here:
INFO: Windows Rundll and Rundll32 Interface
Most importantly:
In your DLL, write the function with the following prototype:
16-bit DLL:
void FAR PASCAL __loads EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
32-bit DLL:
void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
...
On Windows NT, Windows 2000, and Windows XP the behavior of Rundll32.exe is slightly different, in order to accommodate UNICODE command lines.
Windows NT first attempts to GetProcAddress for W. If this entry point is found, then the prototype is assumed to be:
void CALLBACK EntryPointW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow);
This is the same as the ANSI EntryPoint, except that the lpszCmdLine parameter is now a UNICODE string.
As you can see, functions designed to be used with rundll32 do not have a return value. And PrintUIEntry is not documented as using SetLastError() for error reporting. So, in this case, you cannot do any kind of error handling. You will have to use a different API that reports errors.

Related

SetCursorPos function called from Rundll32? [duplicate]

This question already has an answer here:
How to use Rundll32 to execute DLL Function?
(1 answer)
Closed 7 years ago.
How I could properly call the SetCursorPos function from windows RunDll32 application?
If I try this, it sends the cursor to bottom-right corner:
RunDll32.exe user32.dll,SetCursorPos 100, 100
But I'm passing the proper values to its parameters:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms648394%28v=vs.85%29.aspx
PS: I'm not interested in alternatives like for example NirCMD application, I know them, I only would like to know the answer to the question I did, thankyou.
This isn't possible. RunDll32 can only call functions with this signature:
void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
So if you do
RunDll32.exe user32.dll,SetCursorPos 100 100
You are telling RunDll32.exe to do this:
SetCursorPos(0x314159, 0x265358, "100 100", 1)
...were the first two parameters are not in your control (for example, in my machine the call moves the cursor to the upper right).
More info from the docs:
hwnd - window handle that should be used as the owner window for
any windows your DLL creates
hinst - your DLL's instance handle
lpszCmdLine - ASCIIZ command line your DLL should parse
nCmdShow - describes how your DLL's windows should be displayed

Error LNK2019 in visual studio in win32 application?

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.

How to COMPLETELY hide console in a Win32 program?

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)

Why does calling ProcessGroupPolicyEx callback cause an access violation?

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.

What happened to WINVER and _WIN32_WINNT guards in windows.h?

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.

Resources