10.3.1 存取控制.htm
来自「Windows2000后台服务程序开发手册」· HTM 代码 · 共 483 行 · 第 1/5 页
HTM
483 行
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">PACE_UNION AllocateACE(ULONG bACEType, ULONG bACEFlags, <BR> ULONG lAccessMask,PSID pSID ){ <BR> PACE_UNION pReturnACE = NULL; <BR> PBYTE pbBuffer = NULL; <BR> try{ <BR> // 取得ACE中SID的偏移量 <BR> ULONG lSIDOffset = (ULONG)(&((ACCESS_ALLOWED_ACE*)0)->SidStart); <BR> // 取得没有SID的ACE大小 <BR> ULONG lACEStructSize = sizeof(ACCESS_ALLOWED_ACE)- <BR> sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart); <BR> // 取得SID的长度 <BR> ULONG lSIDSize = GetLengthSid(pSID); <BR> // 分配一个缓冲器给ACE <BR> pbBuffer = (PBYTE)LocalAlloc(LPTR, lACEStructSize + lSIDSize); <BR> if (pbBuffer == NULL) <BR> goto leave; <BR> // 复制SID到ACE <BR> if(!CopySid(lSIDSize, (PSID)(pbBuffer+lSIDOffset), pSID)){ <BR> goto leave; <BR> } <BR> pReturnACE = (PACE_UNION) pbBuffer; <BR> pReturnACE->aceHeader.AceSize = (USHORT)(lACEStructSize + lSIDSize); <BR> pReturnACE->aceHeader.AceType = (BYTE)bACEType; <BR> pReturnACE->aceHeader.AceFlags = (BYTE)bACEFlags; <BR> pReturnACE->aceAllowed.Mask = lAccessMask; <BR> leave:; <BR> }catch(...){} <BR> // 在错误实例中释放缓冲器 <BR> if (pbBuffer != (PBYTE)pReturnACE){ <BR> LocalFree(pbBuffer); <BR> } <BR> return (pReturnACE); <BR>}</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>当在使用AllocateAce时,您只须在执行完成时传递回传的ACE给LocalFree。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=Arial color=#3e77d7 size=3
Black><B style="LINE-HEIGHT: 25px">说明</B></FONT> </P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>AllocateAce会传回一个PACE_UNION指标,它是本章先前定义的类型,我选择使用此技巧并以一般的方式表示ACEs。选择特定ACE类型之其中一个也是常见的方法,例如ACCESS_
ALLOWED_ACE,可使用在您的ACE之一般操作上。两种方法都行得通;然而,在本章的一些范例函数中,所使用的是PACE_UNION。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>现在您已经建立了ACE,接下来您必须在对象现存的DACL中搜寻符合的ACEs。您可以经由使用本章先前谈论的ACL读取技巧来实作。在我编写执行此工作程序代码时使用了两个函数:一个用来对照ACEs,另一个则是在ACL中搜寻符合的ACE。</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">BOOL IsEqualACE(PACE_UNION pACE1,PACE_UNION pACE2 ){ <BR> BOOL fReturn =FALSE; <BR> try{{ <BR> if(pACE1->aceHeader.AceType !=pACE2->aceHeader.AceType) <BR> goto leave; <BR> //取得ACE中SID的偏移量 <BR> ULONG lSIDOffset =(ULONG)(&((ACCESS_ALLOWED_ACE*)0)->SidStart); <BR> //取得没有SID的ACE大小 <BR> ULONG lACEStructSize =sizeof(ACCESS_ALLOWED_ACE)- <BR> sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart); <BR> PBYTE pbACE1 =(PBYTE)pACE1; <BR> PBYTE pbACE2 =(PBYTE)pACE2; <BR> fReturn =TRUE; <BR> while(lACEStructSize--) <BR> fReturn =(fReturn &&((pbACE1 [lACEStructSize ] === <BR> pbACE2 [lACEStructSize ]))); <BR> /检查SIDs <BR> fReturn =fReturn &&EqualSid((PSID)(pbACE1+lSIDOffset), <BR> (PSID)(pbACE2+lSIDOffset)); <BR> }leave:; <BR> }catch(...){ <BR> } <BR> return (fReturn); <BR>}</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>以下是第二个函数的内容:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">int FindACEInACL(PACL pACL, PACE_UNION pACE ){ <BR> int nACEIndex =-1; <BR> try{{ <BR> ACL_SIZE_INFORMATION aclSize; <BR> if (!GetAclInformation(pACL, &aclSize, sizeof(aclSize), <BR> AclSizeInformation)){ <BR> goto leave; <BR> } <BR> while (aclSize.AceCount--){ <BR> PACE_UNION pACETemp; <BR> if(!GetAce(pACL, aclSize.AceCount, (PVOID *)&pACETemp)) <BR> goto leave; <BR> if(IsEqualACE(pACETemp, pACE)){ <BR> nACEIndex = (int)aclSize.AceCount; <BR> break; <BR> } <BR> } <BR> }leave:; <BR> }catch(...){ <BR> } <BR> return (nACEIndex); <BR>}</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>FindACEInACL函数会传回DACL中符合的ACE索引值,如果没有找到,则传回
-1值。您应该使用此函数或类似的函数,以找出您打算加到对象DACL的ACEs是否已经存在DACL中(FindACEInACL函数对于寻找您想要使用DeleteAce删除的ACEs也是很有帮助的)。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>现在您已经知道哪些ACEs必须加入DACL及已建立的ACEs,现在是计算新DACL大小的时候了。您可以使用在本章前面出现过的CalculateACLSize函数。它可让您使用现存的ACL、SIDs阵列及ACEs阵列来计算ACL大小。您可以传递NULL给这些参数。在我们的范例中,您有可能会传递一个现存的ACL及ACEs阵列,以在加入ACEs后用来计算新ACL的大小。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>在您分配内存给新的ACL后,应使用InitializeAcl(本章前面讨论过)来初始化新的ACL。接下来您必须从旧的ACL复制ACEs到新的ACL。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>以下的函数显示其实行的方法:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">BOOL CopyACL(PACL pACLDestination, PACL pACLSource ){ <BR> BOOL fReturn = FALSE; <BR> try{{ <BR> // 取得原始ACL中ACEs的数量 <BR> ACL_SIZE_INFORMATION aclSize; <BR> if (!GetAclInformation(pACLSource, &aclSize, <BR> sizeof(aclSize), AclSizeInformation)){ <BR> goto leave; <BR> } <BR> // 使用GetAce及AddAce复制ACEs <BR> for(ULONG lIndex=0;lIndex < aclSize.AceCount;lIndex++){ <BR> ACE_HEADER* pACE; <BR> if(!GetAce(pACLSource, lIndex, (PVOID*)&pACE)) <BR> goto leave; <BR> if(!AddAce(pACLDestination, ACL_REVISION, MAXDWORD, <BR> (PVOID*)pACE, pACE->AceSize)) <BR> goto leave; <BR> } <BR> fReturn = TRUE; <BR> }leave:; <BR> }catch(...){ <BR> } <BR> return (fReturn); <BR>}</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>CopyACL函数相当简单,它只不过重复着通过现存DACL之ACEs并复制每一个到新DACL的动作而已。CopyACL使用了AddAce系统函数,其定义如下:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">BOOL AddAce( <BR> PACL pACL, <BR> DWORD dwACERevision, <BR> DWORD dwStartingACEIndex, <BR> PVOID pACEList, <BR> DWORD dwACEListLength);</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>请注意,AddAce与AddAccessAllowedAce及AddAccessDeniedAce不同。首先您必须提供ACE;系统不会为您收集ACE并放置到DACL里,这意味着您应要定义ACEs的类型,所以AddAce可以把任意类型的ACE加至DACL中;第二,经由使用以0开始的索引值,AddAce可让您决定想要插入新ACE到DACL的位置;第叁,AddAce可让您增加更多的ACE,经由传递连续的ACEs清单给pACEList参数以及清单大小给dwACEListLength参数(不要被清单中的ACEs数量混淆)。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=Arial color=#3e77d7 size=3
Black><B style="LINE-HEIGHT: 25px">说明</B></FONT> </P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>经由允许AddAce复制一个个别函数以呼叫之中所有的原始ACEs,CopyACL范例函数可以更有效地被实作。然而,如此做而取得的ACL结构资讯,应该被视为不透明的。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>在您复制旧DACL到更宽敞的新DACL之后,可以使用AddAce开始加入ACEs。请注意,必须将您的ACEs插入适当的新DACL索引中,以便维护适当的ACE顺序(关于ACE顺序,请参阅 <A
style="LINE-HEIGHT: 25px"
href="http://www.acejoy.com/doc/serverside/10.htm#533_1"
target=_new>表10-6</A> )。您可以使用以下的函数为ACL中的新ACE决定适当的索引值:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">ULONG GetACEInsertionIndex(PACL pDACL, PACE_UNION pACENew){ <BR> ULONG lIndex = (ULONG)-1; <BR> try{{ <BR> // ACL顺序的ACE类型 <BR> ULONG lFilterType[] = { ACCESS_DENIED_ACE_TYPE, <BR> ACCESS_DENIED_OBJECT_ACE_TYPE, <BR> ACCESS_ALLOWED_ACE_TYPE, <BR> ACCESS_ALLOWED_OBJECT_ACE_TYPE}; <BR> // 决定新的ACE应该隶属的群组 <BR> ULONG lNewAceGroup; <BR> for(lNewAceGroup = 0; lNewAceGroup<4 ; lNewAceGroup++){ <BR> if(pACENew->aceHeader.AceType == lFilterType[lNewAceGroup]) <BR> break; <BR> } <BR> // 假如群组 == 4,则这个ACE类型不好 <BR> if(lNewAceGroup==4) <BR> goto leave; <BR> // 假如新的ACE是个继承的ACE,那么它会追求其他的ACEs <BR> if((pACENew->aceHeader.AceFlags & INHERITED_ACE) != 0) <BR> lNewAceGroup+=4; <BR> // 取得ACE总数 <BR> ACL_SIZE_INFORMATION aclSize; <BR> if (!GetAclInformation(pDACL, &aclSize, <BR> sizeof(aclSize), AclSizeInformation)){ <BR> goto leave; <BR> } <BR> // 重复通过ACEs <BR> lIndex = 0; <BR> for(lIndex = 0;lIndex < aclSize.AceCount;lIndex++){ <BR> ACE_HEADER* pACE; <BR> if(!GetAce(pDACL, lIndex, (PVOID*)&pACE)) <BR> goto leave; <BR> // 取得ACL之ACE的群组 <BR> ULONG lAceGroup; <BR> for(lAceGroup = 0; lAceGroup<4 ; lAceGroup++){ <BR> if(pACE->AceType == lFilterType[lAceGroup]) <BR> break; <BR> } <BR> // 测试不好的ACE <BR> if(lAceGroup==4){ <BR> lIndex = (ULONG)-1; <BR> goto leave; <BR> } <BR> // 调整继承 <BR> if((pACE->AceFlags & INHERITED_ACE) != 0) <BR> lAceGroup+=4; <BR> // 假如是相同的群组,那么找出插入点 <BR> if(lAceGroup>=lNewAceGroup) <BR> break; <BR> } <BR> }leave:; <BR> }catch(...){ <BR> } <BR> return (lIndex); <BR>}</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>GetACEInsertionIndex函数会找出您插入新ACE的索引值,并在过程中考虑对象ACEs及ACE继承的部份。在您知道索引值之后,可以呼叫AddAce,以增加新的ACE到ACL中。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>每个新的ACE都会如此做,然后再使用适当的函数设定新的DACL到安全对象。不要忘了在您使用后清理并释放已经分配的任何内存。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>在本章稍早,我曾答应要展示一个在DACL中安排ACEs顺序的范例函数。假如在您彻底完成加入ACEs到DACL前,一点也不想要担心ACE顺序的问题,那么此函数对您可能会很有帮助。以下的OrderDACL函数相当简单,它建立在GetACEInsertionIndex范例函数上:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">BOOL OrderDACL(PACL pDACL ){ <BR> BOOL fReturn = FALSE; <BR> try{{ <BR> // 取得ACL大小及ACE总数 <BR> ACL_SIZE_INFORMATION aclSize; <BR> if (!GetAclInformation(pDACL, &aclSize, <BR> sizeof(aclSize), AclSizeInformation)){ <BR> goto leave; <BR> } <BR> // 为暂时的ACL取得内存 <BR> PACL pTempDACL = (PACL)_alloca(aclSize.AclBytesInUse); <BR> if (pTempDACL==NULL) <BR> goto leave; <BR> // 初始暂时的ACL <BR> if (!InitializeAcl(pTempDACL, aclSize.AclBytesInUse, <BR> ACL_REVISION)) <BR> goto leave; <BR> // 重复通过ACEs <BR> for (ULONG lAceIndex = 0; <BR> lAceIndex < aclSize.AceCount ; lAceIndex++){ <BR> // 取得ACE <BR> PACE_UNION pACE; <BR> if (!GetAce(pDACL, lAceIndex, (PVOID*)&pACE)) <BR> goto leave; <BR> // 找出位置,并且把ACE加入temp DACL <BR> ULONG lWhere = GetACEInsertionIndex(pTempDACL, pACE); <BR> if (!AddAce(pTempDACL, ACL_REVISION, <BR> lWhere, pACE, pACE->AceSize)) <BR> goto leave; <BR> } <BR> // 复制temp DACL到原始的 <BR> CopyMemory(pDACL, pTempDACL, aclSize.AclBytesInUse); <BR> fReturn = TRUE; <BR> } <BR> leave:; <BR> }catch(...){ <BR> } <BR> return (fReturn); <BR>}</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>让我们看看真实世界实作讨论过的技巧范例。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e74d7
size=3><B style="LINE-HEIGHT: 25px">修改DACL范例<BR
style="LINE-HEIGHT: 25px"> </B></FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>我们的范例提供了一组有用的函数给服务开发人员,它显示如何修改一个现存DACL的方法。我使用了Windows中的window站台及桌面安全对象。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e80d7
size=2><B
style="LINE-HEIGHT: 25px"> window站台 </B></FONT>是Windows的安全对象,包含了剪贴簿、一组通用元素及桌面对象的集合。window站台可以是互动式的,意味着使用者可以看到它的「桌面」,一个互动式windows站台也包含键盘及滑鼠资讯。一个程序可以有一个与它相关联的个别windows站台。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e80d7
size=2><B
style="LINE-HEIGHT: 25px"> 桌面 </B></FONT>是一个包含在window站台内的安全对象。一个桌面维护着一个逻辑的显示外观,并包含功能表、视窗及萤幕上的其他可视对象。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>不与使用者互动的服务和互动式桌面没有关联。当使用者登入系统时,互动式window站台(称为WinSta0)的DACL及其预设桌面(称为Default)会被重新设定,并且把此对象的存取权给予使用者。最后,只有已登录的使用者及系统会被授予对此对象的存取权。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e80d7
size=2><B
style="LINE-HEIGHT: 25px"> 问题描述 </B></FONT>服务有时必须在任一信任成员帐户下(使用下一章要讨论的CreateProcessAsUser函数)建立另一个程序,以在目前没有与系统互相作用的使用者环境下建立一个程序。假如此程序需要与使用者互动,而使用者帐户对互动式window站台及预设桌面没有存取权,则系统呼叫CreateProcessAsUser函数时会失败。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>由于发现了这个问题,在建立程序之前,您必须检查这些对象之DACLs的使用者存取权利。假如没有找到这些权利,则它们必须被加入。首先检查权利是很重要的,因为盲目地增加ACE到使用者对象,最后可能会耗尽系统中的资源(通常您只能增加约80个ACEs到window站台)。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e80d7
size=2><B
style="LINE-HEIGHT: 25px"> 解决方案 </B></FONT>现在让我们开始着手处理解决方案。我使用这一节所讨论的工具及观念(和一些范例函数)实作了两个函数:一个可让信任成员存取window站台,而另一个可让信任成员存取桌面。这些函数非常简单。尽管修改对象DACL的程序看起来有点令人怯步,但真实世界中的程序并没有我们所想像的复杂。以下的程序代码可让信任成员存取window站台:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">BOOL AllowAccessToWinSta(PSID psidTrustee, HWINSTA hWinSta ){ <BR> BOOL fReturn = FALSE; <BR> PSECURITY_DESCRIPTOR psdWinSta = NULL; <BR> PACE_UNION pACENew = NULL; <BR> try{{ <BR> // 取得window站台的DACL <BR> PACL pDACLWinSta; <BR> if(GetSecurityInfo(hWinSta, SE_WINDOW_OBJECT, <BR> DACL_SECURITY_INFORMATION, NULL, NULL, &pDACLWinSta, <BR> NULL, &psdWinSta) != ERROR_SUCCESS) <BR> goto leave; <BR> // 分派新的ACE <BR> // 这个存取授予互动地登录的使用者 <BR> PACE_UNION pACENew = AllocateACE(ACCESS_ALLOWED_ACE_TYPE, 0, <BR> DELETE|WRITE_OWNER|WRITE_DAC|READ_CONTROL| <BR> WINSTA_ENUMDESKTOPS|WINSTA_READATTRIBUTES| <BR> WINSTA_ACCESSCLIPBOARD|WINSTA_CREATEDESKTOP| <BR> WINSTA_WRITEATTRIBUTES|WINSTA_ACCESSGLOBALATOMS| <BR> WINSTA_EXITWINDOWS|WINSTA_ENUMERATE|WINSTA_READSCREEN, <BR> psidTrustee); <BR> // ACE是否已经在DACL中? <BR> if (FindACEInACL(pDACLWinSta,pACENew) == -1){ <BR> // 假如没有,计算新的DACL大小 <BR> ULONG lNewACL = CalculateACLSize(pDACLWinSta, NULL, 0, <BR> &pACENew, 1 ); <BR> // 分派内存给新的DACL <BR> PACL pNewDACL = (PACL)_alloca(lNewACL); <BR> if (pNewDACL == NULL) <BR> goto leave; <BR> // 初始ACL <BR> if (!InitializeAcl(pNewDACL, lNewACL, ACL_REVISION)) <BR> goto leave; <BR> // 复制ACL <BR> if (!CopyACL(pNewDACL, pDACLWinSta)) <BR> goto leave; <BR> // 取得新ACE的位置 <BR> ULONG lIndex = GetACEInsertionIndex(pNewDACL, pACENew); <BR> // 增加新的ACE <BR> if (!AddAce(pNewDACL, ACL_REVISION, lIndex, <BR> pACENew, pACENew->aceHeader.AceSize)) <BR> goto leave; <BR> // 设定DACL回到window站台 <BR> if (SetSecurityInfo(hWinSta, SE_WINDOW_OBJECT, <BR> DACL_SECURITY_INFORMATION, NULL, NULL, <BR> pNewDACL, NULL)!=ERROR_SUCCESS) <BR> goto leave; <BR> } <BR> fReturn = TRUE; <BR> }leave:; <BR> }catch(...){ <BR> } <BR> // 清除 <BR> if(pACENew != NULL) <BR> LocalFree(pACENew); <BR> if(psdWinSta != NULL) <BR> LocalFree(psdWinSta); <BR> return (fReturn); <BR>}</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>下一个范例函数可让信任成员存取桌面:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">BOOL AllowAccessToDesktop( PSID psidTrustee, HDESK hDesk ){ <BR> BOOL fReturn = FALSE; <BR> PSECURITY_DESCRIPTOR psdDesk = NULL; <BR> PACE_UNION pACENew = NULL; <BR> try{{ <BR> // 取得桌面的DACL <BR> PACL pDACLDesk; <BR> if(GetSecurityInfo(hDesk, SE_WINDOW_OBJECT, <BR> DACL_SECURITY_INFORMATION, NULL, NULL, &pDACLDesk, <BR> NULL, &psdDesk) != ERROR_SUCCESS) <BR> goto leave; <BR> // 分派新的ACE <BR> // 这个存取授予互动地登录的使用者 <BR> PACE_UNION pACENew = AllocateACE(ACCESS_ALLOWED_ACE_TYPE, 0, <BR> DELETE|WRITE_OWNER|WRITE_DAC|READ_CONTROL| <BR> DESKTOP_READOBJECTS|DESKTOP_CREATEWINDOW| <BR> DESKTOP_CREATEMENU|DESKTOP_HOOKCONTROL| <BR> DESKTOP_JOURNALRECORD|DESKTOP_JOURNALPLAYBACK| <BR> DESKTOP_ENUMERATE|DESKTOP_WRITEOBJECTS|DESKTOP_SWITCHDESKTOP, <BR> psidTrustee); <BR> // ACE是否已经在DACL中? <BR> if (FindACEInACL(pDACLDesk, pACENew) == -1){ <BR> // 假如没有,计算新的DACL大小 <BR> ULONG lNewACL = CalculateACLSize(pDACLDesk, NULL, 0, <BR> &pACENew, 1 ); <BR> // 分配内存给新的DACL <BR> PACL pNewDACL = (PACL)_alloca(lNewACL); <BR> if (pNewDACL == NULL) <BR> goto leave; <BR> // 初始ACL <BR> if (!InitializeAcl(pNewDACL, lNewACL, ACL_REVISION)) <BR> goto leave; <BR> // 复制ACL <BR> if (!CopyACL(pNewDACL, pDACLDesk)) <BR> goto leave; <BR> // 取得新ACE的位置 <BR> ULONG lIndex = GetACEInsertionIndex(pNewDACL, pACENew); <BR> // 增加新的ACE <BR> if (!AddAce(pNewDACL, ACL_REVISION, lIndex, <BR> pACENew, pACENew->aceHeader.AceSize)) <BR> goto leave; <BR> // 设定DACL回到桌面 <BR> if (SetSecurityInfo(hDesk, SE_WINDOW_OBJECT, <BR> DACL_SECURITY_INFORMATION, NULL, NULL, <BR> pNewDACL, NULL)!=ERROR_SUCCESS) <BR> goto leave; <BR> } <BR> fReturn = TRUE; <BR> }leave:; <BR> }catch(...){ <BR> } <BR> // 清除 <BR> if(pACENew != NULL) <BR> LocalFree(pACENew); <BR> if(psdDesk != NULL) <BR> LocalFree(psdDesk); <BR> return (fReturn); <BR>}</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>以下的程序片段显示如何使用这些函数的范例。此程序代码为内建的Everyone群组建立了一个SID,并将它传递到AllowAccessToWinSta及AllowAccessToDesktop函数中:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">PSID psidEveryone; <BR>// 为内建的「Everyone」群组建立一个SID <BR>SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_WORLD_SID_AUTHORITY; <BR>if (!AllocateAndInitializeSid(&sidAuth, 1, SECURITY_WORLD_RID, <BR> 0, 0, 0, 0, 0, 0, 0, &psidEveryone )){ <BR> // 错误 <BR>} <BR>HWINSTA hWinSta = GetProcessWindowStation(); <BR>if (hWinSta == NULL){ <BR> // 错误 <BR>} <BR>AllowAccessToWinSta(psidEveryone, hWinSta); <BR>HDESK hDesk = GetThreadDesktop(GetCurrentThreadId()); <BR>if (hDesk == NULL){ <BR> // 错误 <BR>} <BR>AllowAccessToDesktop(psidEveryone, hDesk);</PRE></FONT></DIV>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?