关闭某个游戏的互斥体 怎么获取游戏互斥体写

&>&&>&&>&&>&R3下用ZwQueryObject和ZwDuplicateObject关闭互斥体和解除文件占用
R3下用ZwQueryObject和ZwDuplicateObject关闭互斥体和解除文件占用
上传大小:10.67MB
不少程序在运行时会创建/打开全局Mutex,来限制用户多开
综合评分:4.3(3位用户评分)
所需积分:0
下载次数:49
审核通过送C币
创建者:frank_
创建者:qq_
创建者:albertbush
课程推荐相关知识库
上传者其他资源上传者专辑
操作系统热门标签
VIP会员动态
您因违反CSDN下载频道规则而被锁定帐户,如有疑问,请联络:!
android服务器底层网络模块的设计方法
所需积分:0
剩余积分:720
您当前C币:0
可兑换下载积分:0
兑换下载分:
兑换失败,您当前C币不够,请先充值C币
消耗C币:0
你当前的下载分为234。
R3下用ZwQueryObject和ZwDuplicateObject关闭互斥体和解除文件占用
会员到期时间:
剩余下载次数:
你还不是VIP会员
开通VIP会员权限,免积分下载
你下载资源过于频繁,请输入验证码
您因违反CSDN下载频道规则而被锁定帐户,如有疑问,请联络:!
若举报审核通过,可奖励20下载分
被举报人:
lixiangminghate
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动色情等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:1120人阅读
& & 不少程序在运行时会创建/打开全局Mutex,来限制用户多开。百度上搜一圈下来,他们的实现基本是这样:
int main(int argc, char* argv[])
HANDLE hMtx = CreateMutex(NULL,false,&process&); //创建一个有名对象,可以在其他进程中访问
if(GetLastError() == ERROR_ALREADY_EXISTS)
//除了创建该对象的进程能进到else分支,其他进程都进入if分支,然后退出
ExitProcess(0);
//do something
}& & 饶过这类限制,我能想到2种方法:
& & 1).修改跳转发生时的条件,不管什么情况都进入else分支
& & &2).删除全局Mutex变量
先简单说下方式1)
if(GetLastError() == ERROR_ALREADY_EXISTS)
dword ptr [__imp__GetLastError@0 (0DC81F0h)]
@ILT+295(__RTC_CheckEsp) (0DC112Ch)
//比较-判断发生在这,只要修改eax的值或者EFlags的值即可
main+7Dh (0DC141Dh) 再看下方式2),a.主要思路是查找目标进程,b.找到后枚举进程所有打开的句柄,c.用ZwDuplicateObject复制句柄,能复制成功的基本是可用的句柄,d.先关闭上次调用ZwDuplicateObject时复制的句柄,然后已DUPLICATE_CLOSE_SOURCE的方式(复制后关闭原句柄)再次复制/关闭句柄。以此关闭限制多开的Mutex。
& & 罗列代码前,先看下这种方式是否具有可行性。首先不杀Mutex句柄,运行同一个进程两次的结果如下
用xuetr关闭进程中的mutex句柄,再次打开:
由上面几张图可知,杀掉全局Mutext后,可以实现进程多开。有了理论的支持,下面开始实际编码。
1.准备工作。代码进行枚举并打开进程,打开进程需要提权,使进程本身具有SE_PRIVILEGE_ENABLED权限。然后导出一堆Zw*函数用于枚举系统和进程的UnDocument API。读者可能知道进程EPROCESS结构中有进程句柄表,记录了进程打开的句柄信息,但是有了SE_PRIVILEGE_ENABLED权限和UnDocument API就能获得目标进程的句柄表了么?貌似也不是~那这不就无解了?在R3下的确很直白的方法,但是,有个很重要的事:进程句柄从4开始计数,每次往上加4,这个可以通过ARK工具查看验证。知道这个事就好办了,大不了在循环中慢慢找过去呗~虽然挨个找过去是一个办法,但是未必每个值为4N的整数就是进程内有效句柄啊~因此,需要用另一个UnDocument
API----ZwDuplicateObject加以验证,如果调用这个函数成功就是一个可用的句柄,然后对这个句柄经行下一步处理。
2.摸排信息。光有进程句柄,同时知道这是一个有效的句柄作用不大。想想GUI进程一堆窗口,每个窗口一个句柄,不可能直接一棍打死吧?所以得摸清楚这个句柄的背景信息,通过调用ZwQueryObject可以获得该句柄的类型名和句柄名。通过字符串比较(wcsstr)找到Mutext对应的句柄。
3.暗杀。以DUPLICATE_CLOSE_SOURCE方式调用DuplicateHandle,意思很直白了,复制的时候把源句柄关闭。谁是源句柄?当然是创建Mutext的进程中的Mutext句柄。读者可以在调试时单步运行到DuplicateHandle,然后观察xuetr中句柄占用情况:调用前,创建这个Mutext的进程对这个句柄的引用数&0,调用成功后引用数=0,因此在创建进程中再也找不到这个句柄的信息了。最后在代码中调用CloseHandle,关闭复制到本进程中的Mutext句柄。当系统发现这个句柄的引用数==0,于是会删除对应的内核对象。当下次运行同一个进程并创建互斥体时,发现系统中并没有这个互斥体,于是顺利的通过if语句往下执行。
#include &stdio.h&
#include &string.h&
#include &windows.h&
#include &winternl.h&
#define STATUS_SUCCESS 0x00UL
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
#define SystemHandleInformation 16
#define SE_DEBUG_PRIVILEGE 0x14
typedef enum _OBJECT_INFORMATION_CLASSEX {
ObjBasicInformation = 0,
ObjNameInformation,
ObjTypeInformation,
} OBJECT_INFORMATION_CLASSEX;
typedef enum _PROCESSINFOCLASSEX
ProcessHandleInformation=20,
}PROCESSINFOCLASSEX;
typedef struct _SYSTEM_HANDLE
ULONG ProcessId;
BYTE ObjectTypeN
ACCESS_MASK GrantA
}SYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION
DWORD HandleC
SYSTEM_HANDLE Handles[1];
}SYSTEM_HANDLE_INFORMATION;
typedef struct _OBJECT_NAME_INFORMATION
UNICODE_STRING ObjectN
}OBJECT_NAME_INFORMATION;
typedef NTSTATUS (WINAPI *ZwQueryInformationProcessProc)(HANDLE,PROCESSINFOCLASSEX,LPVOID,DWORD,PDWORD);
ZwQueryInformationProcessProc ZwQueryInformationP
typedef NTSTATUS (WINAPI *ZwQuerySystemInformationProc)(DWORD,PVOID,DWORD,DWORD*);
ZwQuerySystemInformationProc ZwQuerySystemI
typedef NTSTATUS (WINAPI *ZwQueryObjectProc)(HANDLE,OBJECT_INFORMATION_CLASSEX,PVOID,ULONG,PULONG);
ZwQueryObjectProc ZwQueryO
typedef NTSTATUS (WINAPI *RtlAdjustPrivilegeProc)(DWORD,BOOL,BOOL,PDWORD);
RtlAdjustPrivilegeProc RtlAdjustP
typedef DWORD (WINAPI *ZwSuspendProcessProc)(HANDLE);
ZwSuspendProcessProc ZwSuspendP
typedef DWORD (WINAPI *ZwResumeProcessProc)(HANDLE);
ZwResumeProcessProc ZwResumeP
//进程提权
BOOL ElevatePrivileges()
TOKEN_PRIVILEGES
tkp.PrivilegeCount = 1;
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
return FALSE;
LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid);
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(TOKEN_PRIVILEGES),NULL,NULL))
return FALSE;
return TRUE;
//获得未导出api的地址
BOOL GetUnDocumentAPI()
ZwSuspendProcess = (ZwSuspendProcessProc)
GetProcAddress(GetModuleHandle(L&ntdll.dll&),&ZwSuspendProcess&);
ZwQuerySystemInformation = (ZwQuerySystemInformationProc)
GetProcAddress(GetModuleHandle(L&ntdll.dll&),&ZwQuerySystemInformation&);
ZwQueryObject = (ZwQueryObjectProc)
GetProcAddress(GetModuleHandle(L&ntdll.dll&),&ZwQueryObject&);
ZwResumeProcess = (ZwResumeProcessProc)
GetProcAddress(GetModuleHandle(L&ntdll.dll&),&ZwResumeProcess&);
ZwQueryInformationProcess = (ZwQueryInformationProcessProc)
GetProcAddress(GetModuleHandle(L&ntdll.dll&),&ZwQueryInformationProcess&);
if((ZwSuspendProcess==NULL)||\
(ZwQuerySystemInformation==NULL)||\
(ZwQueryObject==NULL)||\
(ZwResumeProcess==NULL)||\
(ZwQueryInformationProcess==NULL))
return FALSE;
return TRUE;
int main(int argc, char* argv[])
HANDLE duplicateH
HANDLE sourceH
DWORD procHndN
FILE* fp = fopen(&./pid.txt&,&r+&);
fscanf(fp,&%d&,&pid);
fclose(fp);
SYSTEM_HANDLE* currnetH
DWORD buffLen = 0x1000;
SYSTEM_HANDLE_INFORMATION* buff = (SYSTEM_HANDLE_INFORMATION*)malloc(buffLen);
if((ElevatePrivileges()==FALSE)||(GetUnDocumentAPI()==FALSE))
ExitProcess(0);
//初次运行时,不知道缓存区要多大,就试探性的调用该函数。函数返回&span style=&font-family: Arial, Helvetica, sans-&&STATUS_INFO_LENGTH_MISMATCH&/span&&span style=&font-family:Arial, Helvetica, sans-&&
//意为缓存区不够大,然后在下次循环前扩大缓存空间再次调用函数
status = ZwQuerySystemInformation(SystemHandleInformation,buff,buffLen,&buffLen);
if(status == STATUS_INFO_LENGTH_MISMATCH)
free(buff);
buff = (SYSTEM_HANDLE_INFORMATION*)malloc(buffLen);
}while(1);
OBJECT_NAME_INFORMATION* objNameInfo = (OBJECT_NAME_INFORMATION*)malloc(0x1000);
OBJECT_NAME_INFORMATION* objTypeInfo = (OBJECT_NAME_INFORMATION*)malloc(0x1000);
for(int idx=0;idx&buff-&HandleCidx++)
currnetHnd = &(buff-&Handles[idx]);
if(currnetHnd-&ProcessId == pid)
sourceHnd = OpenProcess(PROCESS_ALL_ACCESS|PROCESS_DUP_HANDLE|PROCESS_SUSPEND_RESUME,FALSE,pid);
(ZwSuspendProcess)(sourceHnd);
(ZwQueryInformationProcess)(sourceHnd,ProcessHandleInformation,&procHndNum,sizeof(DWORD),NULL);
//进程有效句柄从4开始,每次以4递增
unsigned short hndNum=4;
for(int idx=0;idx&procHndNhndNum+=4)
//判断是否为有效句柄,返回TRUE,就是有效句柄
if(!DuplicateHandle(sourceHnd,
(HANDLE)hndNum,
GetCurrentProcess(),
&duplicateHnd,0,FALSE,DUPLICATE_SAME_ACCESS))
memset(objNameInfo,0,0x1000);
memset(objTypeInfo,0,0x1000);
//查询句柄类型名和句柄名
ZwQueryObject((HANDLE)duplicateHnd,ObjNameInformation,objNameInfo,0x1000,NULL);
ZwQueryObject((HANDLE)duplicateHnd,ObjTypeInformation,objTypeInfo,0x1000,NULL);
//找到互斥体 比较名字
if(wcsicmp(objTypeInfo-&ObjectName.Buffer,L&mutant&) == 0)
if(wcsstr(objNameInfo-&ObjectName.Buffer,L&process&) != 0)
CloseHandle(duplicateHnd);
DUPLICATE_CLOSE_SOURCE
Closes the source handle. This occurs regardless of any error status returned.
DUPLICATE_SAME_ACCESS
Ignores the dwDesiredAccess parameter. The duplicate handle has the same access as the source handle.
也就是说当我们选择DUPLICATE_CLOSE_SOURCE时,源句柄就会自动关闭了
if(DuplicateHandle(sourceHnd,
(HANDLE)hndNum,
GetCurrentProcess(),
&duplicateHnd,0,FALSE,DUPLICATE_CLOSE_SOURCE))
CloseHandle(duplicateHnd);
ExitProcess(0);
wprintf(L&idx:%03x\nType:%ls\nName:%ls\n&,
(idx+1)*4,
objTypeInfo-&ObjectName.Buffer,
objNameInfo-&ObjectName.Buffer);
wprintf(L&\n\n&);
CloseHandle(duplicateHnd);
(ZwResumeProcess)(sourceHnd);
这段代码做个变体,可以查找进程打开的文件句柄,然后关闭同时删除文件,unlocker的作者大熊猫候佩就是在R3下这么实现结束进程对文件的占用。具体可以搜索他的博客,我就简单罗列一下按他的思路实现的代码
#include &stdio.h&
#include &string.h&
#include &windows.h&
//#include &winternl.h&
#define STATUS_SUCCESS 0x00UL
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) &= 0)
#define SystemHandleInformation 16
#define SE_DEBUG_PRIVILEGE 0x14
typedef struct _IO_STATUS_BLOCK
NTSTATUS S
ULONG_PTR I
}IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef enum _FILE_INFORMATION_CLASS
FileDirectoryInformation=1,
FileFullDirectoryInformation,
FileBothDirectoryInformation,
FileBasicInformation,
FileStandardInformation,
FileInternalInformation,
FileEaInformation,
FileAccessInformation,
FileNameInformation,
FileRenameInformation,
FileLinkInformation,
FileNamesInformation,
FileDispositionInformation,
FilePositionInformation,
FileFullEaInformation,
FileModeInformation,
FileAlignmentInformation,
FileAllInformation,
FileAllocationInformation,
FileEndOfFileInformation,
FileAlternateNameInformation,
FileStreamInformation,
FilePipeInformation,
FilePipeLocalInformation,
FilePipeRemoteInformation,
FileMailslotQueryInformation,
FileMailslotSetInformation,
FileCompressionInformation,
FileObjectIdInformation,
FileCompletionInformation,
FileMoveClusterInformation,
FileQuotaInformation,
FileReparsePointInformation,
FileNetworkOpenInformation,
FileAttributeTagInformation,
FileTrackingInformation,
FileIdBothDirectoryInformation, // 37
FileIdFullDirectoryInformation, // 38
FileValidDataLengthInformation, // 39
FileShortNameInformation,
FileMaximumInformation,
}FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef struct _UNICODE_STRING
USHORT MaximumL
}UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_NAME_INFORMATION
UNICODE_STRING N
}OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
typedef enum _OBJECT_INFORMATION_CLASSEX {
ObjBasicInformation = 0,
ObjNameInformation,
ObjTypeInformation,
} OBJECT_INFORMATION_CLASSEX;
typedef enum _PROCESSINFOCLASSEX
ProcessHandleInformation=20,
}PROCESSINFOCLASSEX;
typedef struct _SYSTEM_HANDLE
ULONG ProcessId;
BYTE ObjectTypeN
ACCESS_MASK GrantA
}SYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION
DWORD HandleC
SYSTEM_HANDLE Handles[1];
}SYSTEM_HANDLE_INFORMATION;
typedef NTSTATUS (NTAPI *ZwQueryInformationFileProc)(HANDLE,PIO_STATUS_BLOCK,PVOID,DWORD,FILE_INFORMATION_CLASS);
ZwQueryInformationFileProc ZwQueryInformationF
typedef NTSTATUS (WINAPI *ZwQueryInformationProcessProc)(HANDLE,PROCESSINFOCLASSEX,LPVOID,DWORD,PDWORD);
ZwQueryInformationProcessProc ZwQueryInformationP
typedef NTSTATUS (WINAPI *ZwQuerySystemInformationProc)(DWORD,PVOID,DWORD,DWORD*);
ZwQuerySystemInformationProc ZwQuerySystemI
typedef NTSTATUS (WINAPI *ZwQueryObjectProc)(HANDLE,OBJECT_INFORMATION_CLASSEX,PVOID,ULONG,PULONG);
ZwQueryObjectProc ZwQueryO
typedef NTSTATUS (WINAPI *RtlAdjustPrivilegeProc)(DWORD,BOOL,BOOL,PDWORD);
RtlAdjustPrivilegeProc RtlAdjustP
typedef DWORD (WINAPI *ZwSuspendProcessProc)(HANDLE);
ZwSuspendProcessProc ZwSuspendP
typedef DWORD (WINAPI *ZwResumeProcessProc)(HANDLE);
ZwResumeProcessProc ZwResumeP
BOOL ElevatePrivileges()
TOKEN_PRIVILEGES
tkp.PrivilegeCount = 1;
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
return FALSE;
LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid);
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(TOKEN_PRIVILEGES),NULL,NULL))
return FALSE;
return TRUE;
BOOL GetUnDocumentAPI()
ZwSuspendProcess = (ZwSuspendProcessProc)
GetProcAddress(GetModuleHandle(L&ntdll.dll&),&ZwSuspendProcess&);
ZwQueryInformationFile = (ZwQueryInformationFileProc)
GetProcAddress(GetModuleHandle(L&ntdll.dll&),&ZwQueryInformationFile&);
ZwQuerySystemInformation = (ZwQuerySystemInformationProc)
GetProcAddress(GetModuleHandle(L&ntdll.dll&),&ZwQuerySystemInformation&);
ZwQueryObject = (ZwQueryObjectProc)
GetProcAddress(GetModuleHandle(L&ntdll.dll&),&ZwQueryObject&);
ZwResumeProcess = (ZwResumeProcessProc)
GetProcAddress(GetModuleHandle(L&ntdll.dll&),&ZwResumeProcess&);
ZwQueryInformationProcess = (ZwQueryInformationProcessProc)
GetProcAddress(GetModuleHandle(L&ntdll.dll&),&ZwQueryInformationProcess&);
if((ZwSuspendProcess==NULL)||\
(ZwQuerySystemInformation==NULL)||\
(ZwQueryObject==NULL)||\
(ZwResumeProcess==NULL)||\
(ZwQueryInformationProcess==NULL))
return FALSE;
return TRUE;
int _tmain(int argc, _TCHAR* argv[])
_tsetlocale(0, _T(&chs&));
HANDLE duplicateH
HANDLE sourceH
DWORD procHndN
FILE* fp = _wfopen(L&./pid.txt&,L&r+&);
fwscanf(fp,L&%d&,&pid);
fclose(fp);
SYSTEM_HANDLE* currnetH
DWORD buffLen = 0x1000;
SYSTEM_HANDLE_INFORMATION* buff = (SYSTEM_HANDLE_INFORMATION*)malloc(buffLen);
IO_STATUS_BLOCK IoStatus ={0};
POBJECT_NAME_INFORMATION objName = NULL;
DWORD allocSize = (DWORD)(sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH*sizeof(WCHAR));
objName = (POBJECT_NAME_INFORMATION)malloc(allocSize);
memset(objName,0,allocSize);
if((ElevatePrivileges()==FALSE)||(GetUnDocumentAPI()==FALSE))
ExitProcess(0);
status = ZwQuerySystemInformation(SystemHandleInformation,buff,buffLen,&buffLen);
if(status == STATUS_INFO_LENGTH_MISMATCH)
free(buff);
buff = (SYSTEM_HANDLE_INFORMATION*)malloc(buffLen);
}while(1);
OBJECT_NAME_INFORMATION* objNameInfo = (OBJECT_NAME_INFORMATION*)malloc(0x1000);
OBJECT_NAME_INFORMATION* objTypeInfo = (OBJECT_NAME_INFORMATION*)malloc(0x1000);
for(int idx=0;idx&buff-&HandleCidx++)
currnetHnd = &(buff-&Handles[idx]);
if(currnetHnd-&ProcessId == pid)
sourceHnd = OpenProcess(PROCESS_ALL_ACCESS|PROCESS_DUP_HANDLE|PROCESS_SUSPEND_RESUME,FALSE,pid);
//(ZwSuspendProcess)(sourceHnd);
(ZwQueryInformationProcess)(sourceHnd,ProcessHandleInformation,&procHndNum,sizeof(DWORD),NULL);
//进程有效句柄从4开始,每次以4递增
unsigned short hndNum=4;
for(int idx=0;idx&procHndNhndNum+=4)
//判断是否为有效句柄,返回TRUE,就是有效句柄
if(!DuplicateHandle(sourceHnd,
(HANDLE)hndNum,
GetCurrentProcess(),
&duplicateHnd,0,FALSE,DUPLICATE_SAME_ACCESS))
memset(objNameInfo,0,0x1000);
memset(objTypeInfo,0,0x1000);
ZwQueryObject((HANDLE)duplicateHnd,ObjNameInformation,objNameInfo,0x1000,NULL);
ZwQueryObject((HANDLE)duplicateHnd,ObjTypeInformation,objTypeInfo,0x1000,NULL);
//找到互斥体 比较名字
if(wcsicmp(objTypeInfo-&Name.Buffer,L&file&) == 0)
NTSTATUS status =-1;
memset(objName,0,allocSize);
status = ZwQueryInformationFile((HANDLE)duplicateHnd,&IoStatus,objName,allocSize,FileNameInformation);
if(NT_SUCCESS(status))
if(wcsstr((wchar_t*)&(objName-&Name.Buffer), L&unlock&)!=0)
if(DuplicateHandle(sourceHnd,
(HANDLE)hndNum,
GetCurrentProcess(),
&duplicateHnd,0,FALSE,DUPLICATE_CLOSE_SOURCE))
CloseHandle(duplicateHnd);
//DeleteFile();
ExitProcess(0);
wprintf(L&%ls\n&,&(objName-&Name.Buffer));
//(ZwResumeProcess)(sourceHnd);
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:99042次
积分:2523
积分:2523
排名:第12535名
原创:143篇
转载:73篇
评论:16条
阅读:1067
阅读:1410
文章:17篇
阅读:4724
文章:11篇
阅读:5234
文章:19篇
阅读:5481
文章:33篇
阅读:23858
(3)(14)(11)(13)(12)(9)(17)(6)(11)(12)(10)(3)(5)(2)(15)(4)(4)(1)(1)(5)(2)(11)(6)(4)(5)(4)(15)(12)(6)(1)找出当前系统是否已经存在指定进程的实例。如果没有则创建一个互斥体。CreateMutex()函数可用来创建一个有名或无名的互斥量对象,其函数原型为
HANDLE CreateMutex(
  LPSECURITY_ATTRIBUTESlpMutexAttributes, // 指向安全属性的指针
  BOOLbInitialOwner, // 初始化互斥对象的所有者
  LPCTSTRlpName // 指向互斥对象名的指针
创建一个(MUTEX)
  Long,
如执行成功,就返回互斥体对象的句柄;零表示出错。会设置GetLastError。即使返回的是一个有效句柄,但倘若指定的名字已经存在,GetLastError也会设为ERROR_ALREADY_EXISTS
  参数表
  参数 类型及说明
  lpMutexAttributes SECURITY_ATTRIBUTES,指定一个SECURITY_ATTRIBUTES结构,或传递零值(将参数声明为ByVal As Long,并传递零值),表示使用不允许继承的默认描述符
  bInitialOwner Long,如创建进程希望立即拥有互斥体,则设为TRUE。一个互斥体同时只能由一个线程拥有
  lpName String,指定互斥体对象的名字。用vbNullString创建一个未命名的互斥体对象。如已经存在拥有这个名字的一个事件,则打开现有的已命名互斥体。这个名字可能不与现有的事件、信号机、可等待计时器或文件映射相符
一旦不再需要,注意必须用CloseHandle函数将互斥体句柄关闭。从属于它的所有句柄都被关闭后,就会删除对象
  进程中止前,一定要释放互斥体,如不慎未采取这个措施,就会将这个互斥体标记为废弃,并自动释放所有权。共享这个互斥体的其他也许仍然能够用它,但会接收到一个废弃状态信息,指出上一个所有进程未能正常关闭。这种状况是否会造成影响取决于涉及到的具体应用程序
(1)、 h_mutex1=CreateMutex(NULL,FALSE,"mutex_for_readcount");//创建一个互斥体
  (2)、HANDLE m_hMutex = CreateMutex(NULL, FALSE, "Sample07");// 检查错误代码
  if (GetLastError() == ERROR_ALREADY_EXISTS)
  // 如果已有互斥量存在则释放句柄并复位互斥量
  CloseHandle(m_hMutex);
  m_hMutex = NULL;
  // 程序退出
  return FALSE;
  //上面这段代码演示了有名互斥量在进程互斥中的用法。代码的核心是CreateMutex()对有名互斥量的创建。
  CreateMutex() 用于有独占要求的程序 (在其进程运行期间不允许其他使用此端口设备的程序运行,或不允许同名程序运行)。
阅读(...) 评论()

我要回帖

更多关于 公司关闭通知怎么写 的文章

 

随机推荐