|
Please note that the Winlogon Notification have been removed as of Windows Vista.
Assaf
|
|
|
|
|
Anyone knows of any solution of how to implement this on Windows 7?
Thanks.
|
|
|
|
|
Hello Tony,
Let me just thank you for wonderful post, It helps me a lot.. I have a question to ask..
I've made a service in which i monitored whenever the user logs off or logged on system, Now i need to retrieve user details before shell is created, So i tried your code and started my service from there, But i didn't get expected result, Can you point out what am i doing wrong and how to rectify it...
Thanks
|
|
|
|
|
As old as this posted code is, it appears to be popular...
Thank you, Tony, for the demonstration/example, you should've received more +5 votes ;^).
I am a total newb who never made a DLL or even coded in c/c++/c# before... please be gentle while I learn the correct syntactical referencing, etc.
My questions have to do with creating this in MinGW C/C++
1) anyone here succeeded in creating a workable DLL for WinLogon with MinGW?
--------------------------
I am uncertain what the problem is with the code I created based on Tony's example.
At first I was having a real problem with the Alias (Entry Points) issues (learning about Export), but I think I sorted that out...
...now all my variations compile seemingly okay, i.e., no Entry Point error when I run my dll, but then nothing happens when I run it.
I think it may have to do with lacking export with regard to the main WIN function... but I haven't a clue really...
I will provide an example of how far I got, and some methods (gcc/g++) used to build, but forgive me, it would be too volumnous to try to expose all the approaches I tried...
---------------------------
Essentially I took and coded the aliases / entry points right into the DLL (since I am not using the code to also create an exe), rather than relying on a .def to create a library (although I did that too, and seemingly correctly).
To mention... the road there included variations on recreating my own .def file (using dlltool to compile it from a primary sample.dll) and then compiling with a .a or .lib ...kinds of things.
I actually was successful compiling the DLL with proper entry point aliasing (I think) using several of these different methods (with and without my own external header or lib files)... the only error that was persistent was the "missing entry point" that it seemed I had to figure out each time,
BUT,
...no matter my success, when calling a successfully compiled DLL -->> nothing happens.
Here is a sample of the code using MinGW and using either gcc or g++ to compile it:
//sample3.cpp
// to test, RUN: RUNDLL32 C:\Temp\sample3.dll,StartProcessAtWinLogon
// this one compiles okay with gcc -Wall -shared %FILENAME% -o %FILENAMENOEXT%.DLL
// several other command approaches listed below
#include <windows.h>
#include <Winwlx.h>
extern "C" // this cleans up the prefix on the entry handles, but not the suffixes [@nn]
{
__declspec (dllexport) void __stdcall StartProcessAtWinLogon (void)
{
return;
}
__declspec (dllexport) void __stdcall StopProcessAtWinLogoff (void)
{
return;
}
} /// end Extern C
// droped the T macro since its not really needed in this application (or so I have read)...
PROCESS_INFORMATION g_pi;
TCHAR g_szPath[] = "c:\\temp\\test.exe";
//I keep testing with variation on the path syntax to be sure its not as simple as my exe is not launching
//I have dropped the terminate stuff for now while testing
// SafeTerminateProcess(HANDLE hProcess, UINT uExitCode);
//Entrance function for the DLL (LibMain | DllMain)
//This is where I think the problem is. I think when using MinGW may require dllexport with this
// but I have been trying attempts with that with no success (compiling yes, but triggering a response when run, no)
BOOL WINAPI LibMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
DisableThreadLibraryCalls (hInstance);
}
break;
}
return TRUE;
}
//Event handler for the Winlogon Logon event
VOID APIENTRY StartProcessAtWinLogon (PWLX_NOTIFICATION_INFO pInfo)
{
STARTUPINFO si;
si.cb = sizeof(STARTUPINFO);
si.lpReserved = NULL;
si.lpTitle = NULL;
si.lpDesktop = "WinSta0\\Default";
si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L;
si.dwFlags = 0;;
si.wShowWindow = SW_SHOW;
si.lpReserved2 = NULL;
si.cbReserved2 = 0;
CreateProcess(NULL, g_szPath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE,
NULL, NULL, &si, &g_pi);
}
//Event handler for the Winlogon Logoff event.
VOID APIENTRY StopProcessAtWinLogoff (PWLX_NOTIFICATION_INFO pInfo)
{
//terminates the process
// SafeTerminateProcess(g_pi.hProcess, 0xDEADBEEF);
}
//other event handlers
VOID APIENTRY YOUR_EVENT_HANDLERS (PWLX_NOTIFICATION_INFO pInfo)
{
//code
}
// ...End Code
##################################
Without getting into specifics, here are some of the various commands I have worked with for compiling (of course, using alternate versions from teh code provided above).....
// to test my dll I do RUN:
// RUNDLL32 C:\Temp\sample3.dll,StartProcessAtWinLogon <optional arguments>
// compile: gcc -Wall -shared %FILENAME% -o %FILENAMENOEXT%2.DLL
// g++ -WI --add-stdcall-alias -shared %FILENAME% -o %FILENAMENOEXT%2.DLL
// g++ -WI,--add-stdcall-alias -shared %FILENAME% -o %FILENAMENOEXT%2.DLL
// when working with a .def file I used dlltool on a compiled sample to retrieve the exports
// in order to create the /lib, then recompiled the sample.dll for the final (seemingly successfully... variations...
// dlltool -A -D sample2.dll -l sample2dll.lib
// dlltool -d -k sample.def -l sample2dll.lib
// gcc -Wall -shared %FILENAME% -o %FILENAMENOEXT%3.DLL -lsample2dll
// gcc -Wall -shared %FILENAME% -o %FILENAMENOEXT%3.DLL -L %PATH% -l sample2dll
// http://www.mingw.org/wiki/sampleDLL
// run first: g++ -c -DBUILDING_EXAMPLE_DLL %FILENAMENOEXT%.cpp
// run next: g++ -shared -o %FILENAMENOEXT%.dll %FILENAMENOEXT%.o -Wl,--out-implib,lib%FILENAMENOEXT%.a
// gcc -Wall -shared %FILENAME% -o %FILENAMENOEXT%.DLL
####################################
I would think you can simply call this dll like any other (using Rundll32) for testing
I am about ready to give up... I thought this should be fairly straightforward, however, now I wonder that without taking a course ...maybe its unreasonable to spend more time on this.
Anyone got any pointers?
Thanks.
|
|
|
|
|
Follwoup...
When I edit relevant line to this line instead
extern "C" __declspec (dllexport) BOOL WINAPI LibMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
I get all the entry points, like so..
...these two now appearing, which I could not achieve before...
LibMain
LibMain@12
...and then these 4, which I have been able to get for sometime now...
StartProcessAtWinLogon
StartProcessAtWinLogon@0
StartProcessAtWinLogoff
StartProcessAtWinLogoff@0
...so now I am thinking, although entry point issues may be relevant my real problem probably has something to do with I know squat about what I need to issue (command) for compiling this correctly so Win sees it as a proper dll.
Your insights appreciated ;^)
Cheers,
TwoHawks
|
|
|
|
|
Hmmm, well not that I know much if anything about what I am doing yet, but I am obtaining some results, so I am posting them here.
Here is the new sample3.cpp file I am building the dll from:
##################
// sample.cpp
// build with command: gcc -Wall -shared %FILENAME% -o %FILENAMENOEXT%.DLL
// test with RUNDLL32 C:\Temp\sample3.dll,<EntryPoint> <optional arguments>
// Note that this DLL gets created with both cleaned aliases and the stdcall kind (with @nn appendage)
#include <windows.h>
#include <Winwlx.h>
#include <stdio.h>
PROCESS_INFORMATION g_pi;
TCHAR g_szPath[] = "C:\\Temp\\test.exe";
extern "C" __declspec (dllexport) BOOL WINAPI LibMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
DisableThreadLibraryCalls (hInstance);
}
break;
}
return TRUE;
}
// test with RUNDLL32 C:\Temp\sample3.dll,WinMain
extern "C" __declspec (dllexport) int WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
MessageBox(0,"Hello, Windows","MinGW Test Program",MB_OK);
return 0;
}
//Event handler for the Winlogon Logon event
// test with RUNDLL32 C:\Temp\sample3.dll,StartProcessAtWinLogon
extern "C" __declspec (dllexport) VOID APIENTRY StartProcessAtWinLogon (PWLX_NOTIFICATION_INFO pInfo)
{
STARTUPINFO si;
si.cb = sizeof(STARTUPINFO);
si.lpReserved = NULL;
si.lpTitle = NULL;
si.lpDesktop = "WinSta0\\Default";
si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L;
si.dwFlags = 0;;
si.wShowWindow = SW_SHOW;
si.lpReserved2 = NULL;
si.cbReserved2 = 0;
CreateProcess(NULL, g_szPath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE,
NULL, NULL, &si, &g_pi);
}
//Event handler for the Winlogon Logoff event.
extern "C" __declspec (dllexport) VOID APIENTRY StopProcessAtWinLogoff (PWLX_NOTIFICATION_INFO pInfo)
{
//terminates the process
// SafeTerminateProcess(g_pi.hProcess, 0xDEADBEEF);
}
//other event handlers
extern "C" __declspec (dllexport) VOID APIENTRY YOUR_EVENT_HANDLERS (PWLX_NOTIFICATION_INFO pInfo)
{
//code
}
// ... end file
####################################################
All entry points are responsive. This does not mean this is being done right, but at lest I have a basis to study and learn what's happening.
I sure hope some of you experts chime in with some pointers ;^)
Thanks.
TwoHawks
|
|
|
|
|
The sample can run the notpad, but I just see it after I log into OS.
Can I see the notepad's UI and logon's UI at the same time, when OS show logon's UI?
no fate
|
|
|
|
|
error LNK2001: unresolved external symbol "int __cdecl SafeTerminateProcess(void *,unsigned int)" (?SafeTerminateProcess@@YAHPAXI@Z)
Debug/Rajesh.dll : fatal error LNK1120: 1 unresolved externals
|
|
|
|
|
HI,
I have created a Win-logon Notification package which will call a function at the time of logon. I need to get log-on username in this function.
I have used GetUserNameEx() function, but this returns the SYSTEM name itself as the username but not the user who has log-on to system.
This might be probelm with Winlogon.exe , becasue this exe will run with SYSTEM user which will not be accessible.
If any body have information about why this probelm is comiing please tell me.
Thanks and Regads,
Padmaja.
|
|
|
|
|
The WLX_NOTIFICATION_INFO structure contains the user name of the use who logged on. It's passed to all of the function handlers you provide. Just write a handler for the logon event and pull the data there.
typedef struct _WLX_NOTIFICATION_INFO
{
ULONG Size;
ULONG Flags;
PWSTR UserName;
PWSTR Domain;
PWSTR WindowStation;
HANDLE hToken;
HDESK hDesktop;
PFNMSGECALLBACK pStatusCallback;
} WLX_NOTIFICATION_INFO,
Thanks,
Andy
|
|
|
|
|
Hi ...
I think that your service is running on system, So whenever you will query the user name using GetUserNameEx()on a service, it would return you system. As it is running on it.
For your problem you need to use this function.
BOOL WTSQuerySessionInformation(
__in HANDLE hServer,
__in DWORD SessionId,
__in WTS_INFO_CLASS WTSInfoClass,
__out LPTSTR *ppBuffer,
__out DWORD *pBytesReturned
);
Give a valid SessionId and it would return you the valid user name in LPTSTR *ppBuffer.
|
|
|
|
|
Guys! I can't compile this sample, it gives me a lot of errors, can somebody post the complete code?
|
|
|
|
|
This feature don't works on vista because it has been removed.
see the link http://download.microsoft.com/download/3/b/a/3ba6d659-6e39-4cd7-b3a2-9c96482f5353/Winlogon%20Notification%20Packages%20Removed%20Impact%20on%20Windows%20Vista%20Planning%20and%20Deployment.doc[^]
A work around to get session event notification is to create a service and getting notifications in callback function. Using the API RegisterServiceCtrlHandlerEx and you will have a code like this.
Bye
DWORD WINAPI CallbackServiceCtrlHandler (
DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
LPVOID lpContext
)
{
DWORD dwErrorCode = NO_ERROR;
switch(dwControl)
{
case SERVICE_CONTROL_CUSTOM_MESSAGE:
dwErrorCode = NO_ERROR;
break;
case SERVICE_CONTROL_PAUSE:
m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
dwErrorCode = NO_ERROR;
break;
case SERVICE_CONTROL_CONTINUE:
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
dwErrorCode = NO_ERROR;
break;
case SERVICE_CONTROL_STOP:
m_ServiceStatus.dwWin32ExitCode = 0;
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
SetServiceStatus (m_ServiceStatusHandle,&m_ServiceStatus);
bRunning=false;
dwErrorCode = NO_ERROR;
break;
case SERVICE_CONTROL_INTERROGATE:
dwErrorCode = NO_ERROR;
break;
// Notification management of sessions events.
case SERVICE_CONTROL_SESSIONCHANGE:
FILE * f = fopen ("c:\\debug.txt","a");
Beep (1000, 500);
if (dwEventType == WTS_CONSOLE_CONNECT)
{
// A session was connected to the console terminal..
fputs ("A session was connected to the console terminal\n" , f);
}
if (dwEventType == WTS_CONSOLE_DISCONNECT)
{
// A session was disconnected from the console terminal.
fputs ("A session was disconnected from the console terminal\n" , f);
}
if (dwEventType == WTS_REMOTE_CONNECT)
{
// A session was connected to the remote terminal.
fputs ("A session was connected to the remote terminal\n" , f);
}
if (dwEventType == WTS_REMOTE_DISCONNECT)
{
// A session was disconnected from the remote terminal.
fputs ("A session was disconnected from the remote terminal\n" , f);
}
if (dwEventType == WTS_SESSION_LOGON)
{
// A user has logged on to the session.
fputs ("A user has logged on to the session\n" , f);
}
if (dwEventType == WTS_SESSION_LOGOFF)
{
// A user has logged off the session.
fputs ("A user has logged off the session\n" , f);
}
if (dwEventType == WTS_SESSION_LOCK)
{
// A session has been locked.
fputs ("A session has been locked\n" , f);
}
if (dwEventType == WTS_SESSION_UNLOCK)
{
// A session has been unlocked.
fputs ("A session has been unlocked\n" , f);
}
if (dwEventType == WTS_SESSION_REMOTE_CONTROL)
{
// A session has changed its remote controlled status.
fputs ("A session has changed its remote controlled status\n" , f);
}
fclose (f);
break;
}
return dwErrorCode;
}
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
m_ServiceStatus.dwServiceType = SERVICE_WIN32;
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
// Very important tell to the system that you want session changes with SERVICE_ACCEPT_SESSIONCHANGE flag.
m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SESSIONCHANGE;
m_ServiceStatus.dwWin32ExitCode = 0;
m_ServiceStatus.dwServiceSpecificExitCode = 0;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
m_ServiceStatusHandle = RegisterServiceCtrlHandlerEx (TEXT("CustomSvc"), CallbackServiceCtrlHandler, NULL);
if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
return;
}
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus))
{
}
bRunning=true;
while(bRunning)
{
Sleep(3000);
//Place Your Code for processing here....
}
return;
}
|
|
|
|
|
hi all,
i am working on msgina.dll winlogon package i want to modify the change password dialog i have created and added two buttons and one edit control on change password dialog in place of it's original control (original control will be hide)in that case my added controls are not changed as xp style look.
anyone tell me how to create the manifest file? and how to use it??
thankx in advance
|
|
|
|
|
Hi all,
When I get the message lock event,how I can write program to pass the username and password to bypass logon windows?
Call any API or SDK to do it to bypass login window when windlow is locked?
Thanks,
johngle
|
|
|
|
|
Hello,
I'm afraid I haven't manged to learn C++ yet.
I do a whole lot of API calls from VB just to get it to do what I need, so I bumped into this code snippet.
I do a lot of work with folks with disabilities and I need to be able to run special programs that allow them to login when they can't use a keyboard or mouse.
This looks like the right bit of code but it is incomplete and I don't know enough to fill in the blanks so I can compile it with VS6.
If I have the Dll I can call it from my VB6 apps and life is much easier for a lot of folks!
I'm expecting to need a
StartProcessAtStartUp event
rather than StartProcessAtWinLogon...
Any help at all would be greatly appreciated!
If anyone knows a better method I'm all ears.
Vindalf
Mind-over-Machine
|
|
|
|
|
Does Winlogon notification packages work in Non-Domain environments?
I mean, do they function in environments that does not have a Windows Domain(Active Directory) Setup, something like Workgroup environments.
Kindly let me know for any pointers.
Bala
|
|
|
|
|
I'm trying to compile this code with VS.NET 2003 with no luck.
Anyone have a sample code?
Thanks.
|
|
|
|
|
Hi Folks,
I have developed an Event DLL (detecting Login, Logout, Start Screensaver and Stop Screensaver) in Delphi and works fine on my own pc and the rest of my co-workers development machines.
I have begun to test the Event DLL on a clean install of XP + Service pack.
The Event DLL doesn’t work anymore???
I have debug output to text files but the DLL doesn’t seem to be called at all.
I was wondering if there is another piece of s/w that I need installed on my test Pc.
The registry is updated via a registry key script and this hasn’t changed and works fine on all my development pc’s.
Any help much appreciated?
Cheers,
Con
|
|
|
|
|
Hi Folks,
I got this sorted, turned out to have a file dependency with the Borland Memory Manager “Borlndmm.dll”
Cheers,
Con
|
|
|
|
|
I've run into an odd problem using a release version of this DLL. I'm using the sample code from this page virtually verbatim to launch a simple application that writes a log entry to a text file and then exits. The application should be launched when a user logs in, just as in the sample. Debug versions of the DLL (compiled with VC++ 6) launch the external application just fine, but release versions of the same DLL don't. File names, registry entries, etc., are all identical. The compiler gives me no hints, warnings, or other messages when I build the release version, so I'm at a bit of a loss as to why this might occur. Has anyone else noticed this?
Thanks,
Aaron
|
|
|
|
|
Hello,
I built a Winlogon notification dll, which works fine on XP. The same DLL does not neem to work on Windows 2003. My dll is used by teh system, because I cannot overwrite it, however It does,t seem to be called at login time. I display a message box, write to a text file, start Noteped etc., none of them happens.
I tried logging in to teh Windows 2003 terminal Server in different ways:
1. from the console as administrator,
2. from an XP client using Remote Desktop Connection, as administrator
3. from an XP client using Remote Desktop Connection, as regular user
None of the above works. If you have any ideas, let me know.
Thanks,
Alpar
|
|
|
|
|
This is a non-article, surely?
There is nothing here that isn't already in the MSDN article here (URL correct at time of writing. If broken, search MSDN for "WLX_NOTIFICATION_INFO")
|
|
|
|
|
A winlogon notification dll does not seem to be allowed to work for more than two or three minutes. If you specify Asynchronous=0, winlogon will wait, but not infinite (then, the process can still work, but the shell is already being loaded). Unfortunately, I did not find any hints anywhere how to change this timeout. Is it possible? Or is there a workaround?
|
|
|
|
|
Just a guess, but the 'TermSrv' item in my XP system has an additional registry value called 'MaxWait' which is a DWORD value set to 600 decimal. If that is in seconds, we are talking about a 10 minute wait! Give it a try and let us know!
|
|
|
|
|