﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-我的玻璃盒子-随笔分类-Windows开发</title><link>http://www.cppblog.com/epubcn/category/6040.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 08 Jan 2009 14:19:37 GMT</lastBuildDate><pubDate>Thu, 08 Jan 2009 14:19:37 GMT</pubDate><ttl>60</ttl><item><title>[转载]Vista下服务与桌面互交</title><link>http://www.cppblog.com/epubcn/archive/2009/01/06/71356.html</link><dc:creator>深蓝色系统</dc:creator><author>深蓝色系统</author><pubDate>Tue, 06 Jan 2009 08:59:00 GMT</pubDate><guid>http://www.cppblog.com/epubcn/archive/2009/01/06/71356.html</guid><wfw:comment>http://www.cppblog.com/epubcn/comments/71356.html</wfw:comment><comments>http://www.cppblog.com/epubcn/archive/2009/01/06/71356.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/epubcn/comments/commentRss/71356.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/epubcn/services/trackbacks/71356.html</trackback:ping><description><![CDATA[原文链接：http://www.cnblogs.com/lifeengines/archive/2008/08/26/1277054.html<br><br>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 本来在Vista之前服务与桌面互交是一件很容易的事情,自从Vista把服务都挪到Session 0
中运行去而且不可以跨Session之后,问题就复杂了许多,有时候我就在想这些问题是否真的不得不解决而且似乎对于安全并未带来多大提升的更改总是让人
头疼,Google了一些文档,抄袭了不少代码我是如下实现的</p>
<p>&nbsp;这个函数抄自winehq网站,顺便不得不说一下winehq的代码是很值得参考的</p>
<div class="cnblogs_code"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">BOOL&nbsp;WINAPI&nbsp;EnablePrivilege(LPSTR&nbsp;lpPrivilegeName,&nbsp;BOOL&nbsp;bEnable)<br>
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">{<br>
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;TOKEN_PRIVILEGES&nbsp;Privileges;<br>
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hToken;<br>
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;bResult;<br>
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">OpenProcessToken(GetCurrentProcess(),&nbsp;TOKEN_QUERY,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">hToken))<br>
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;FALSE;<br>
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;"><br>
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Privileges.PrivilegeCount&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #800080;">1</span><span style="color: #000000;">;<br>
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Privileges.Privileges[</span><span style="color: #800080;">0</span><span style="color: #000000;">].Attributes&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(bEnable)&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;SE_PRIVILEGE_ENABLED&nbsp;:&nbsp;</span><span style="color: #800080;">0</span><span style="color: #000000;">;<br>
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;"><br>
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">LookupPrivilegeValue(NULL,&nbsp;lpPrivilegeName,<br>
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">Privileges.Privileges[</span><span style="color: #800080;">0</span><span style="color: #000000;">].Luid))<br>
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br>
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hToken);<br>
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;FALSE;<br>
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br>
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;"><br>
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;bResult&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;AdjustTokenPrivileges(hToken,&nbsp;FALSE,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">Privileges,&nbsp;</span><span style="color: #800080;">0</span><span style="color: #000000;">,&nbsp;NULL,&nbsp;NULL);<br>
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;"><br>
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hToken);<br>
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;"><br>
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;bResult;<br>
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">}</span></div>
<p>&nbsp;</p>
<p>EnablePrivilege用来提升本进程权限,因为我们的核心思路是用CreateProcessAsUser创建进程到需要互交的Session,</p>
<p>&nbsp;</p>
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">保证拥有权限</span><span style="color: #008000;"><br>
</span><span style="color: #000000;">EnablePrivilege(SE_TCB_NAME,&nbsp;TRUE);&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;EnablePrivilege(SE_CHANGE_NOTIFY_NAME,&nbsp;TRUE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;EnablePrivilege(SE_INCREASE_QUOTA_NAME,&nbsp;TRUE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME,&nbsp;TRUE);<br>
<br>
</span><span style="color: #008000;">//</span><span style="color: #008000;">获取当前进程的灵牌</span><span style="color: #008000;"><br>
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hTokenThis&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;NULL;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hTokenDup&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;NULL;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hThisProcess&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;GetCurrentProcess();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OpenProcessToken(hThisProcess,&nbsp;TOKEN_ALL_ACCESS,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">hTokenThis);<br>
</span><span style="color: #008000;">//</span><span style="color: #008000;">复制令牌</span><span style="color: #008000;"><br>
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DuplicateTokenEx(hTokenThis,&nbsp;MAXIMUM_ALLOWED,NULL,&nbsp;SecurityIdentification,&nbsp;TokenPrimary,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">hTokenDup);<br>
</span><span style="color: #008000;">//</span><span style="color: #008000;">枚举所有Session,本来还有一个WTSGetActiveConsoleSessionId,不过这个函数在win2000下只有Server版本安装WTS才可以</span><span style="color: #008000;"><br>
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PWTS_SESSION_INFO&nbsp;pSInfo;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;pCInfo&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #800080;">0</span><span style="color: #000000;">;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE,</span><span style="color: #800080;">0</span><span style="color: #000000;">,</span><span style="color: #800080;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">pSInfo,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">pCInfo);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;dwSessionId&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #800080;">0</span><span style="color: #000000;">;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i</span><span style="color: #000000;">=</span><span style="color: #800080;">0</span><span style="color: #000000;">;i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">pCInfo;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(pSInfo[i].State&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;WTSActive)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dwSessionId&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;pSInfo[i].SessionId;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">DWORD&nbsp;dwSessionId&nbsp;=&nbsp;WTSGetActiveConsoleSessionId();<br>
</span><span style="color: #008000;">//</span><span style="color: #008000;">替换令牌,关键地方,我们并不需要以Session用户创建进程,只需要替换令牌就可以了</span><span style="color: #008000;"><br>
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetTokenInformation(hTokenDup,&nbsp;TokenSessionId,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">dwSessionId,&nbsp;</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(DWORD));<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;STARTUPINFO&nbsp;si&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;{</span><span style="color: #800080;">0</span><span style="color: #000000;">};<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PROCESS_INFORMATION&nbsp;pi&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;{</span><span style="color: #800080;">0</span><span style="color: #000000;">};<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;si.cb&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(si);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;si.lpDesktop&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">WinSta0\\Default</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;dwCreationFlag&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;NORMAL_PRIORITY_CLASS&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;CREATE_NEW_CONSOLE&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;CREATE_UNICODE_ENVIRONMENT;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;pPath[MAX_PATH</span><span style="color: #000000;">*</span><span style="color: #800080;">2</span><span style="color: #000000;">];<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetModuleFileName(NULL,pPath,</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(pPath));<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcat(pPath,</span><span style="color: #800000;">"</span><span style="color: #800000;">&nbsp;-work</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPVOID&nbsp;pEnv;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CreateEnvironmentBlock(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">pEnv,hTokenDup,FALSE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">CreateProcessAsUser(hTokenDup,NULL,pPath,NULL,NULL,FALSE,dwCreationFlag,pEnv,NULL,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">si,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">pi))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;<br>
</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;p&nbsp;=&nbsp;GetLastError();<br>
</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;=&nbsp;0;</span><span style="color: #008000;"><br>
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WaitForSingleObject(pi.hProcess,INFINITE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hTokenDup);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hTokenThis);<br>
</span><br>
这样我们的程序就可以和桌面互交了,这只是核心,其余牵涉多用户切换这些还需要另外考虑<br><br><img src ="http://www.cppblog.com/epubcn/aggbug/71356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/epubcn/" target="_blank">深蓝色系统</a> 2009-01-06 16:59 <a href="http://www.cppblog.com/epubcn/archive/2009/01/06/71356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转帖）Windows同步API （二）&amp;mdash;&amp;mdash; Semaphore</title><link>http://www.cppblog.com/epubcn/archive/2008/02/03/42430.html</link><dc:creator>深蓝色系统</dc:creator><author>深蓝色系统</author><pubDate>Sun, 03 Feb 2008 02:45:00 GMT</pubDate><guid>http://www.cppblog.com/epubcn/archive/2008/02/03/42430.html</guid><wfw:comment>http://www.cppblog.com/epubcn/comments/42430.html</wfw:comment><comments>http://www.cppblog.com/epubcn/archive/2008/02/03/42430.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/epubcn/comments/commentRss/42430.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/epubcn/services/trackbacks/42430.html</trackback:ping><description><![CDATA[<p>原文链接：<a title=http://www.cppblog.com/wangjt/archive/2008/02/01/42362.html href="http://www.cppblog.com/wangjt/archive/2008/02/01/42362.html">http://www.cppblog.com/wangjt/archive/2008/02/01/42362.html</a></p>
<p>Semaphore是旗语的意思，在Windows中，Semaphore对象用来控制对资源的并发访问数。Semaphore对象具有一个计数值，当值大于0时，Semaphore被置信号，当计数值等于0时，Semaphore被清除信号。每次针对Semaphore的wait functions返回时，计数值被减1，调用ReleaseSemaphore可以将计数值增加 lReleaseCount 参数值指定的值。
<p>CreateSemaphore函数用于创建一个Semaphore
<p>HANDLE CreateSemaphore(<br>LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,<br>LONG lInitialCount,<br>LONG lMaximumCount,<br>LPCTSTR lpName<br>);
<p>lpSemaphoreAttributes为安全属性，<br>lInitialCount为Semaphore的初始值，<br>lMaximumCount为最大值，<br>lpName为Semaphore对象的名字，NULL表示创建匿名Semaphore
<p>此外还可以调用OpenSemaphore来打开已经创建的非匿名Semaphore
<p>HANDLE OpenSemaphore(<br>DWORD dwDesiredAccess,<br>BOOL bInheritHandle,<br>LPCTSTR lpName<br>);
<p>调用ReleaseSemaphore增加Semaphore计算值
<p>BOOL ReleaseSemaphore(<br>HANDLE hSemaphore,<br>LONG lReleaseCount,<br>LPLONG lpPreviousCount<br>);
<p>lpReleaseCount参数表示要增加的数值，<br>lpPreviousCount参数用于返回之前的计算值，如果不需要可以设置为NULL
<p>比如我们要控制到服务器的连接数不超过10个，可以创建一个Semaphore，初值为10，每当要连接到服务器时，使用WaitForSingleObject请求Semaphore，当成功返回后再尝试连接到服务器，当连接失败或连接使用完后释放时，调用ReleaseSemaphore增加Semaphore计数值。 </p>
<img src ="http://www.cppblog.com/epubcn/aggbug/42430.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/epubcn/" target="_blank">深蓝色系统</a> 2008-02-03 10:45 <a href="http://www.cppblog.com/epubcn/archive/2008/02/03/42430.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转帖）Windows同步API （二）&amp;mdash;&amp;mdash; Event</title><link>http://www.cppblog.com/epubcn/archive/2008/02/03/42429.html</link><dc:creator>深蓝色系统</dc:creator><author>深蓝色系统</author><pubDate>Sun, 03 Feb 2008 02:44:00 GMT</pubDate><guid>http://www.cppblog.com/epubcn/archive/2008/02/03/42429.html</guid><wfw:comment>http://www.cppblog.com/epubcn/comments/42429.html</wfw:comment><comments>http://www.cppblog.com/epubcn/archive/2008/02/03/42429.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/epubcn/comments/commentRss/42429.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/epubcn/services/trackbacks/42429.html</trackback:ping><description><![CDATA[<p>原文链接：<a title=http://www.cppblog.com/wangjt/archive/2008/02/01/42312.html href="http://www.cppblog.com/wangjt/archive/2008/02/01/42312.html">http://www.cppblog.com/wangjt/archive/2008/02/01/42312.html</a></p>
<p>　　Event即事件是一种用于进行线程/进程间同步的对象，事件有置位和复位两种状态，当线程通过waiting functions等待Event对象置位时该线程将进入阻塞状态，当该Event对象被置位或等待超时后，等待的线程将恢复执行。Event可以用在一个线程要等待其它线程时。<br>可以使用CreateEvent创建Event对象<br>HANDLE WINAPI CreateEvent(<br>&nbsp;&nbsp;&nbsp; LPSECURITY_ATTRIBUTES lpEventAttributes,<br>&nbsp;&nbsp;&nbsp; BOOL bManualReset,<br>&nbsp;&nbsp;&nbsp; BOOL bInitialState,<br>&nbsp;&nbsp;&nbsp; LPCTSTR lpName<br>);<br>lpEventAttributes用于指定Event对象的安全属性，包括句柄是否可被子进程继承和对象的安全描述符。可设置NULL取默认安全属性。<br>bManualReset表明Event对象是否需要手动复位。如果该参数为TRUE，则Event对象需要通过ResetEvent函数手动复位。如果该参数为FALSE，则Event被创建为自动复位的Event，任何等待的线程被恢复执行后，该Event将被系统自动复位。打个比方，如果有10个线程在等待一个Event，这时将Event置位，如果这是个手动复位Event，那么这10个线程将被依次唤醒直到通过ResetEvent调用将该Event复位；如果Event为自动复位Event，那么10个线程中的第一个被唤醒后Event被自动复位，其它线程将继续等待。<br>bInitialState参数表明Event对象被创建后默认是否置位。<br>lpName参数是Event的名字，可以为空表明将创建匿名Event。<br>CreateEvent函数在调用成功后返回Event句柄。如果同名Event已经存在，则返回这个已经存在了的Event的句柄，此时调用GetLastError函数将返回 ERROR_ALREADY_EXISTS。<br>还可以通过OpenEvent打开一个已经创建的非匿名Event<br>HANDLE WINAPI OpenEvent(<br>&nbsp;&nbsp;&nbsp; DWORD dwDesiredAccess,<br>&nbsp;&nbsp;&nbsp; BOOL bInheritHandle,<br>&nbsp;&nbsp;&nbsp; LPCTSTR lpName<br>);<br>在创建或打开了Event对象之后，可以使用SetEvent和ResetEvent函数来置位或复位一个Event对象。<br>BOOL WINAPI SetEvent(<br>&nbsp;&nbsp;&nbsp; HANDLE hEvent<br>);<br>BOOL WINAPI ResetEvent(<br>&nbsp;&nbsp;&nbsp; HANDLE hEvent<br>);<br>要等待一个或多个Event对象置位可以使用wait functions。<br>简单示例，一个线程不停读取用户输入并放入message列表，另一个线程模拟将message发送出去，如果没有消息，则发送线程处于阻塞状态等待，一旦有消息录入，输入线程将event置位，发送线程即被激活并逐个发送消息。<br>#include "stdafx.h"<br>#include &lt;windows.h&gt;<br>#include &lt;tchar.h&gt;<br>#include &lt;iostream&gt;<br>#include &lt;list&gt;<br>#include &lt;string&gt;<br>using namespace std;
<p>#ifdef _UNICODE<br>typedef wstring tstring;<br>#define tcout wcout<br>#define tcin wcin<br>#else<br>typedef string tstring;<br>#define tcout cout<br>#define tcin cin<br>#endif /* _UNICODE */
<p>typedef list&lt;tstring&gt; StringList;
<p>HANDLE hMutex = NULL;<br>HANDLE hEvent = NULL;<br>HANDLE hSendThread = NULL;<br>StringList messages;
<p>bool isRunning;
<p>DWORD WINAPI SendThreadProc(LPVOID lpThreadParameter)<br>{<br>DWORD dw;<br>while(isRunning)<br>{<br>&nbsp; dw = WaitForSingleObject(hEvent, INFINITE);<br>&nbsp; if(dw != WAIT_OBJECT_0)<br>&nbsp; {<br>&nbsp;&nbsp; tcout &lt;&lt; _T("Wait error.") &lt;&lt; endl;<br>&nbsp;&nbsp; return -1;<br>&nbsp; }<br>&nbsp; dw = WaitForSingleObject(hMutex, INFINITE);<br>&nbsp; if(WAIT_OBJECT_0 != dw &amp;&amp; WAIT_ABANDONED != dw)<br>&nbsp; {<br>&nbsp;&nbsp; tcout &lt;&lt; _T("Wait error.") &lt;&lt; endl;<br>&nbsp;&nbsp; return -2;<br>&nbsp; }
<p>&nbsp; StringList list(messages);<br>&nbsp; messages.clear();
<p>&nbsp; ReleaseMutex(hMutex);
<p>&nbsp; for(StringList::iterator i = list.begin(); i != list.end(); i++)<br>&nbsp; {<br>&nbsp;&nbsp; Sleep(1000); //休眠1秒模拟发送所耗时间
<p>&nbsp;&nbsp; tcout &lt;&lt; _T("/* Send Message:") &lt;&lt; *i &lt;&lt; _T(" */");<br>&nbsp; }
<p>}
<p>return 0;<br>}
<p>int _tmain(int argc, _TCHAR* argv[])<br>{<br>hMutex = CreateMutex(NULL, FALSE, NULL);<br>hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);<br>isRunning = true;
<p>hSendThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendThreadProc, NULL, 0, NULL);
<p>while(isRunning)<br>{<br>&nbsp; tstring s;<br>&nbsp; tcin &gt;&gt; s;<br>&nbsp; if(s == _T("quit"))<br>&nbsp; {<br>&nbsp;&nbsp; isRunning = true;<br>&nbsp;&nbsp; break;<br>&nbsp; }
<p>&nbsp; DWORD dw = WaitForSingleObject(hMutex, INFINITE);<br>&nbsp; if(WAIT_OBJECT_0 != dw &amp;&amp; WAIT_ABANDONED != dw)<br>&nbsp; {<br>&nbsp;&nbsp; tcout &lt;&lt; _T("Wait error.") &lt;&lt; endl;<br>&nbsp;&nbsp; return -1;<br>&nbsp; }<br>&nbsp; messages.push_back(s);<br>&nbsp; ReleaseMutex(hMutex);<br>&nbsp; SetEvent(hEvent);<br>}
<p>CloseHandle(hMutex);<br>CloseHandle(hEvent);<br>CloseHandle(hSendThread);
<p>return 0;
<p>}</p>
<img src ="http://www.cppblog.com/epubcn/aggbug/42429.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/epubcn/" target="_blank">深蓝色系统</a> 2008-02-03 10:44 <a href="http://www.cppblog.com/epubcn/archive/2008/02/03/42429.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转帖）Windows同步API （一）&amp;mdash;&amp;mdash; Mutex</title><link>http://www.cppblog.com/epubcn/archive/2008/02/03/42428.html</link><dc:creator>深蓝色系统</dc:creator><author>深蓝色系统</author><pubDate>Sun, 03 Feb 2008 02:43:00 GMT</pubDate><guid>http://www.cppblog.com/epubcn/archive/2008/02/03/42428.html</guid><wfw:comment>http://www.cppblog.com/epubcn/comments/42428.html</wfw:comment><comments>http://www.cppblog.com/epubcn/archive/2008/02/03/42428.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/epubcn/comments/commentRss/42428.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/epubcn/services/trackbacks/42428.html</trackback:ping><description><![CDATA[<p>原文链接：<a title=http://www.cppblog.com/wangjt/archive/2008/01/30/42235.html href="http://www.cppblog.com/wangjt/archive/2008/01/30/42235.html">http://www.cppblog.com/wangjt/archive/2008/01/30/42235.html</a></p>
<p>Mutex是互斥体的意思，当一个线程持有一个Mutex时，其它线程申请持有同一个Mutex会被阻塞，因此可以通过Mutex来保证对某一资源的互斥访问（即同一时间最多只有一个线程访问）。<br>调用CreateMutex可以创建或打开一个Mutex对象，其原型如下
<p>HANDLE CreateMutex(<br>&nbsp; LPSECURITY_ATTRIBUTES lpMutexAttributes,<br>&nbsp; BOOL bInitialOwner,<br>&nbsp; LPCTSTR lpName<br>);
<p>其中参数lpMutexAttributes用来设定Mutex对象的安全描述符和是否允许子进程继承句柄。bInitialOwner表明是否将Mutex的持有者设置为调用线程。lpName参数设置Mutex的名字，该名字区分大小写并不能包含"\"，最大长度为MAX_PATH，可设置为NULL表明该Mutex为匿名对象。<br>如果调用成功，则返回Mutex的句柄，否则返回NULL，如果lpName不为NULL且调用前同名的Mutex已被创建，则返回同名Mutex的句柄，此时调用GetLastError将返回ERROR_ALREADY_EXISTS，参数bInitialOwner将被忽略。
<p>还可以调用OpenMutex打开创建的非匿名Mutex，原型如下
<p>HANDLE OpenMutex(<br>&nbsp; DWORD dwDesiredAccess,<br>&nbsp; BOOL bInheritHandle,<br>&nbsp; LPCTSTR lpName<br>);
<p>在成功创建或打开Mutex后，可以使用wait functions来等待并获取Mutex的持有权。
<p>下面的例子用来通过Mutex对象控制某一应用程序只运行一次
<p>&nbsp;&nbsp;&nbsp; int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HANDLE hMutex = CreateMutex(NULL, FALSE, "Mutex_Only_One_Instance_Allowed");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (NULL == hMutex)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Error("Create mutex error.");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD dw = WaitForSingleObject(hMutex, 0);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (WAIT_FAILED == dw)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Error("Wait for mutex error.");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle(hMutex); // 释放句柄，当指向同一系统对象的所有句柄释放后，该对象将被删除。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (WAIT_TIMEOUT == dw)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 另外一个实例正在运行<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle(hMutex);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 没有其它实例在运行，本实例将继续运行<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 在此实现必要的功能性代码，如创建窗口，进入消息循环<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...............
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReleaseMutex(hMutex); // 释放hMutex的持有权，注意这并不等同于删除Mutex对象<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle(hMutex);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp;&nbsp; }
<p>其中WaitForSingleObject是等待特定对象发出信号（signaled），而Mutex对象在没有任何线程持有时会发出信号。</p>
<img src ="http://www.cppblog.com/epubcn/aggbug/42428.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/epubcn/" target="_blank">深蓝色系统</a> 2008-02-03 10:43 <a href="http://www.cppblog.com/epubcn/archive/2008/02/03/42428.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>