#!/usr/bin/env python

# This file is part of Window-Switch.
# Copyright (c) 2009-2013 Antoine Martin <antoine@nagafix.co.uk>
# Window-Switch is released under the terms of the GNU GPL v3


from winswitch.util.simple_logger import Logger
from winswitch.globals import WIN32
logger = Logger("rdp_common_util")

TERMINAL_SERVER_PATH = r"System\CurrentControlSet\Control\Terminal Server"
TERMINAL_SERVER_DENY_KEY = r"fDenyTSConnections"

NODESKTOP_PATH = r"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer"
NODESKTOP_KEY = r"NoDesktop"

RDP_PATH = r"%s\WinStations\RDP-Tcp" % TERMINAL_SERVER_PATH
RDP_PORT_KEY = r"PortNumber"
RDP_PRODUCT = r"WdName"

if WIN32:
	import win32api, win32con	#@UnresolvedImport


def get_WindowsEditionWarning():
	import string
	edition = filter(lambda x: x in string.printable, get_WindowsEdition()).replace("Microsoft Windows", "").strip()
	if edition=="unknown":
		return	None
	def inlist(names):
		for x in names:
			if edition.find(x)>=0:
				return	True
		return False
	if edition.find("Windows XP")>=0:
		#XP: Only XP Pro supports RDP server:
		if edition.find("XP Home")>=0:
			return	edition
		if edition.find("XP Pro")>=0:
			return	None
		logger.slog("unknown edition of XP: %s" % edition)
		return edition
	if edition.find("Vista")>=0:
		# see here for details:
		#http://windows.microsoft.com/en-US/windows-vista/Connect-to-another-computer-using-Remote-Desktop-Connection
		if inlist(["Starter", "Home Basic", "Home Premium"]):
			return	edition
		return None
	if edition.find(" 7 ")>=0 or edition.find(" 8 "):
		# see here for details:
		#http://windows.microsoft.com/en-US/windows7/Remote-Desktop-Connection-frequently-asked-questions
		if inlist(["Professional", "Ultimate", "Enterprise"]):
			return	None
		if inlist(["Starter", "Home Basic", "Home Premium"]):
			return	edition
		logger.slog("unknown edition of Windows 7/8: %s" % edition)
		return	edition
	logger.slog("unknown/unsupported windows edition: %s" % edition)
	return	None


WindowsEdition = None
def get_WindowsEdition():
	global WindowsEdition
	if WindowsEdition is None:
		WindowsEdition = "unknown"
		try:
			import wmi			#@UnresolvedImport
			c = wmi.WMI()
			for os in c.Win32_OperatingSystem():
				WindowsEdition = os.Caption
		except:
			pass
		logger.slog("=%s" % WindowsEdition)
	return	WindowsEdition

def supports_rdp():
	if not WIN32 or get_WindowsEditionWarning():
		return	False
	ts_denied = get_DenyTSConnections()
	return	ts_denied is not None and ts_denied==0

def get_DenyTSConnections():
	return	get_registry_int(win32con.HKEY_LOCAL_MACHINE, TERMINAL_SERVER_PATH, TERMINAL_SERVER_DENY_KEY)

def enable_TS():
	set_registry_int(win32con.HKEY_LOCAL_MACHINE, TERMINAL_SERVER_PATH, TERMINAL_SERVER_DENY_KEY, 0)

def supports_rdp_seamless_explorer():
	if not WIN32:
		return	False
	nodesktop = get_NoDesktop()
	return	nodesktop and nodesktop==1

def get_NoDesktop():
	return	get_registry_int(win32con.HKEY_CURRENT_USER, NODESKTOP_PATH, NODESKTOP_KEY)

def get_RDP_Port():
	return	get_registry_int(win32con.HKEY_LOCAL_MACHINE, RDP_PATH, RDP_PORT_KEY)

def get_RDP_ProductVersion():
	return	get_registry_value(win32con.HKEY_LOCAL_MACHINE, RDP_PATH, RDP_PRODUCT)


#
# Registry access utility
#
def get_registry_int(key, reg_path, entry):
	value = get_registry_value(key, reg_path, entry)
	if value is None:
		return	None
	return int(value)
def get_registry_value(key, reg_path, entry):
	try:
		hKey = win32api.RegOpenKey(key, reg_path)
		value, value_type = win32api.RegQueryValueEx(hKey, entry)
		win32api.RegCloseKey(hKey)
		logger.slog("value=%s, value_type=%s" % (value, value_type), key, reg_path, entry)
		return	value
	except Exception, e:
		logger.serr(None, e, key, reg_path, entry)
		return	None

def set_registry_int(key, reg_path, entry, value):
	logger.slog(None, key, reg_path, entry, value)
	try:
		hKey = win32api.RegOpenKeyEx(key, reg_path, 0, win32con.KEY_SET_VALUE)
		win32api.RegSetValueEx(hKey, entry, 0, win32con.REG_DWORD, value)
		win32api.RegCloseKey(hKey)
		return	True
	except Exception, e:
		logger.serr(None, e, key, reg_path, entry, value)
		return	False
