This code implements a Python solution for locking a workstation via a secure screensaver as recommended by the Microsoft KB article Q262646. It sets up a secure screensaver, then calls it. Really simple code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | """
Locks the users workstation, for Windows NT and 2000
Design philosophy for this was simple, create a utility to lock
a users' workstation, without messing up their screensaver settings.
"""
import win32con
import win32api
#########################################
#Set up the two methods we'll use in this program:
#########################################
#We need a method to check what they have setup for their screensaver, so
#that we can return things to what they should be once the workstation is
#locked:
def queryHKCUValues(valuePath, valueName):
settingsDict = {}
#First, we need to open a handle to the relevant HIVE in the registry...
keyHandle = win32api.RegOpenKeyEx(win32con.HKEY_CURRENT_USER, valuePath, 0, win32con.KEY_READ)
for value in valueName:
(valueData, valueType) = win32api.RegQueryValueEx(keyHandle, value)
settingsDict[value] = [valueData, valueType]
keyHandle.Close()
#This dictionary now holds all the info that we'll need to put things back where
#they belong once we're done...
return settingsDict
#This method we will use to 'tidy up' after ourselves...
def returnHKCUValues(valuePath, valueDict):
#First, we need to open a handle to the relevant HIVE in the registry...
keyHandle = win32api.RegOpenKeyEx(win32con.HKEY_CURRENT_USER, valuePath, 0, win32con.KEY_WRITE)
valueDictKeys = valueDict.keys()
#'Unpack' the dictionary values back into the registry where they belong:
for value in valueDictKeys:
win32api.RegSetValueEx(keyHandle, value, 0, valueDict[value][1], valueDict[value][0])
keyHandle.Close()
#########################################
#On to the real work now!
#########################################
#Before we begin, lets record the state of the values that we'll be working with:
tempDict = queryHKCUValues('Control Panel\Desktop', ['ScreenSaveActive', 'ScreenSaverIsSecure', 'SCRNSAVE.EXE'])
#Now we can assign our own values to these without fear of messing them up:
keyHandle = win32api.RegOpenKeyEx(win32con.HKEY_CURRENT_USER, 'Control Panel\Desktop', 0, win32con.KEY_WRITE)
#Now that we have the handle, we can use it to setup the relevant settings in the registry.
#These ensure that every time this program is run, the screensaver is in a predictable state.
win32api.RegSetValueEx(keyHandle, 'ScreenSaveActive', 0, win32con.REG_SZ, '1')
win32api.RegSetValueEx(keyHandle, 'ScreenSaverIsSecure', 0, win32con.REG_SZ, '1')
win32api.RegSetValueEx(keyHandle, 'SCRNSAVE.EXE', 0, win32con.REG_SZ, 'logon.scr')
#Now that we've satisfied all assumptions, we can close the handle:
keyHandle.Close()
#Now that we now that a secure screensaver is guaranteed, we send the
#'Launch Screensaver' message, as recommended in Microsoft KB article
#Q262646. Don't ask why we have to call it twice to get it to work...
win32api.SendMessage(win32con.HWND_TOPMOST, win32con.WM_SYSCOMMAND, win32con.SC_SCREENSAVE, 0)
win32api.SendMessage(win32con.HWND_TOPMOST, win32con.WM_SYSCOMMAND, win32con.SC_SCREENSAVE, 0)
#Now that the workstation is locked, we will return everything to the way
#it was beforehand:
returnHKCUValues('Control Panel\Desktop', tempDict)
#Finally, we will force the value of the screen saver grace period to zero
#so that locking happens instantaneously upon the launching of the
#screensaver. This setting requires a reboot to take effect, so we will
#simply force it here everytime to make sure that it is always set for
#when the user reboots:
keyHandle = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows NT\CurrentVersion\Winlogon', 0, win32con.KEY_WRITE)
win32api.RegSetValueEx(keyHandle, 'ScreenSaverGracePeriod', 0, win32con.REG_SZ, '0')
keyHandle.Close()
#Have fun!
#God bless Python and the Win32 extensions library ;-)
#esrever_otua
|
Despite a fairly simple-seeming implementation, my experiments with this raised some fairly interesting issues, I'd love input from anyone else who sees this and tries it. However, first things first, I'll answer the question, 'why would anyone want to use this?' This code is useful for a number of reasons, first off, it works on both Windows NT 4.0 Server and Workstation, and Windows 2000 Pro and Server etc. It probably works on most Win32 platforms, but I've only tested it on those mentioned. It serves two purposes: 1) it can be used to automatically lock workstations that are set to automatically log in by adding an appropriate command line to the Run key in the registry. As any sysadmin will know, there are lots of 'NT' applications out there that must run on logged-in servers to work. This means lots of servers with the auto-logon parameters set (which is a massive security hole). This allows those servers to be set up in a secure manner by locking themselves as soon as they log in. It can also be compiled with py2exe into a nicely working executable and run whenever (put a shortcut on the desktop, it's a lot easier than CTRL+ALT+DEL-ing and waiting for the screen to refresh before locking it and walking away...) I did run in to one issue when exploring this function, and I'd love comment on this: 1) when run on NT, unless you use the SendMessage call twice, the screen saver simply appears then bombs out again
So, enjoy, and have fun coding with python... esrever_otua
A problem, if a screen saver is set to "None"
Easier way. I was looking to do the same thing and came across your code. It looks kind of complicated to me. Here's what worked for me.
import os
winpath=os.environ['windir']#yes, brackets not parentheses
path to windows installation directory,
usually c:\windows or c:\winnt
os.system(winpath + '\system32\rundll32 user32.dll, LockWorkStation')
if you want, you can use the newer subprocess.Popen() or subprocess.call()
Only works in 2000+. The 'LockWorkStation' function doesn't exist in Windows NT (when this recipe was written).
The only way is to call the screensaver :)