#coding=utf-8
import ctypes
from ctypes import wintypes
#某些結構體可能會在Windows各個版本中有所差異,是以MSDN中并沒有詳述這些結構體。
#這裡的定義都是在VS2008下找到的
class ACLStruct(ctypes.Structure):
_fields_ = [("AclRevision", wintypes.BYTE),
("Sbz1", wintypes.BYTE),
("AclSize", wintypes.WORD),
("AceCount", wintypes.WORD),
("Sbz2", wintypes.WORD)]
class SID_IDENTIFIER_AUTHORITYStruct(ctypes.Structure):
_fields_ = [("Value", wintypes.BYTE * 6)]
class SIDStruct(ctypes.Structure):
_fields_ = [("Revision", wintypes.BYTE),
("SubAuthorityCount", wintypes.BYTE),
("IdentifierAuthority", SID_IDENTIFIER_AUTHORITYStruct),
("SubAuthority", wintypes.DWORD * 1)]
class SECURITY_DESCRIPTORStruct(ctypes.Structure):
_fields_ = [("Revision", wintypes.BYTE),
("Sbz1", wintypes.BYTE),
("Control", wintypes.WORD),
("Owner", ctypes.POINTER(SIDStruct)),
("Group", ctypes.POINTER(SIDStruct)),
("Sacl", ctypes.POINTER(ACLStruct)),
("Dacl", ctypes.POINTER(ACLStruct))]
class SECURITY_ATTRIBUTESStruct(ctypes.Structure):
_fields_ = [("nLength", wintypes.DWORD),
("lpSecurityDescriptor", ctypes.POINTER(SECURITY_DESCRIPTORStruct)),
("bInheritHandle", wintypes.BOOL)]
try:
Dll_Advapi32 = ctypes.windll.LoadLibrary("Advapi32.dll")
_InitializeSecurityDescriptor = Dll_Advapi32.InitializeSecurityDescriptor
_InitializeSecurityDescriptor.argtypes = [ctypes.c_void_p, wintypes.DWORD]
_InitializeSecurityDescriptor.restype = wintypes.BOOL
_SetSecurityDescriptorDacl = Dll_Advapi32.SetSecurityDescriptorDacl
_SetSecurityDescriptorDacl.argtypes = [ctypes.c_void_p, wintypes.BOOL, ctypes.c_void_p, wintypes.BOOL]
_SetSecurityDescriptorDacl.restype = wintypes.BOOL
#如果name要是unicode,可以把這裡改成CreateEventW,還要改參數類型
_CreateEvent = ctypes.windll.kernel32.CreateEventA
_CreateEvent.argtypes = [ctypes.c_void_p, wintypes.BOOL, wintypes.BOOL, wintypes.LPCSTR]
_CreateEvent.restype = wintypes.HANDLE
_WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
_WaitForSingleObject.argtypes = [wintypes.HANDLE, wintypes.DWORD]
_WaitForSingleObject.restype = wintypes.DWORD
_SetEvent = ctypes.windll.kernel32.SetEvent
_SetEvent.argtypes = [wintypes.HANDLE]
_SetEvent.restype = wintypes.BOOL
_CloseHandle = ctypes.windll.kernel32.CloseHandle
_CloseHandle.argtypes = [wintypes.HANDLE]
_CloseHandle.restype = wintypes.BOOL
except Exception, e:
logger.error("init win32 sync object interface fail, error[%s]", str(e))
raise
#Win32 Event的封裝。name須為ANSI字元串。不可重入
class Win32SyncObject(object):
def __init__(self, name):
self.handle = None
try:
#設定安全屬性是為了使服務中建立的鎖也能在使用者程序中通路,如果使用預設屬性,會拒絕通路
#如果不需要考慮這個問題,則可以去掉上述相關結構體的定義和這段設定安全屬性的代碼,直接使用預設值None
sd = SECURITY_DESCRIPTORStruct()
if not _InitializeSecurityDescriptor(ctypes.byref(sd), 1):
err_code = ctypes.GetLastError()
err_msg = ctypes.FormatError(err_code)
raise ctypes.WinError(err_code, err_msg)
if not _SetSecurityDescriptorDacl(ctypes.byref(sd), True, None, False):
err_code = ctypes.GetLastError()
err_msg = ctypes.FormatError(err_code)
raise ctypes.WinError(err_code, err_msg)
sa = SECURITY_ATTRIBUTESStruct()
sa.nLength = 12
sa.lpSecurityDescriptor = ctypes.pointer(sd)
sa.bInheritHandle = False
self.handle = _CreateEvent(ctypes.byref(sa), False, False, name)
except Exception, e:
self.handle = None
raise
if not self.handle:
err_code = ctypes.GetLastError()
err_msg = ctypes.FormatError(err_code)
raise ctypes.WinError(err_code, err_msg)
else:
if 0 == ctypes.GetLastError():#此時是建立
_SetEvent(self.handle)
def __del__(self):
pass
#應該關閉句柄,但是這個析構執行的時機有點奇怪,此時self.handle已經被釋放了
#哪位大神能解釋一下嗎
#_CloseHandle(self.handle)
#self.handle = None
def acquire(self):
try:
ret = _WaitForSingleObject(self.handle, 0xFFFFFFFF)#永久等待
except Exception, e:
raise
if ret in (0, 0x80):
return True
else:
err_code = ctypes.GetLastError()
err_msg = ctypes.FormatError(err_code)
return False
def release(self):
try:
ret = _SetEvent(self.handle)
except Exception, e:
raise
if not ret:
err_code = ctypes.GetLastError()
err_msg = ctypes.FormatError(err_code)
return False
else:
return True
#使用示例
#全局跨程序通路必須是Global命名空間下的
if_lock = Win32SyncObject(name = "Global\\CAA_{6A6B3EE2-8F6C-41f0-AA08-763AAE0C1D98}")
if_lock.acquire()
if_lock.release()
print "OK"