2005-07-26 21:17:06 +00:00
|
|
|
/*
|
|
|
|
* ReactOS MARTA provider
|
2006-01-22 03:50:36 +00:00
|
|
|
* Copyright (C) 2005 - 2006 ReactOS Team
|
2005-07-26 21:17:06 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
/* $Id$
|
|
|
|
*
|
|
|
|
* PROJECT: ReactOS MARTA provider
|
|
|
|
* FILE: lib/ntmarta/ntmarta.c
|
|
|
|
* PURPOSE: ReactOS MARTA provider
|
|
|
|
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
|
|
|
|
*
|
|
|
|
* UPDATE HISTORY:
|
|
|
|
* 07/26/2005 Created
|
|
|
|
*/
|
|
|
|
#include <ntmarta.h>
|
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
HINSTANCE hDllInstance;
|
|
|
|
|
2006-03-09 20:15:11 +00:00
|
|
|
static ACCESS_MODE
|
|
|
|
AccpGetAceAccessMode(IN PACE_HEADER AceHeader)
|
|
|
|
{
|
|
|
|
ACCESS_MODE Mode = NOT_USED_ACCESS;
|
|
|
|
|
|
|
|
switch (AceHeader->AceType)
|
|
|
|
{
|
|
|
|
case ACCESS_ALLOWED_ACE_TYPE:
|
|
|
|
case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
|
|
|
|
case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
|
|
|
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
|
|
|
|
Mode = GRANT_ACCESS;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ACCESS_DENIED_ACE_TYPE:
|
|
|
|
case ACCESS_DENIED_CALLBACK_ACE_TYPE:
|
|
|
|
case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
|
|
|
|
case ACCESS_DENIED_OBJECT_ACE_TYPE:
|
|
|
|
Mode = DENY_ACCESS;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SYSTEM_AUDIT_ACE_TYPE:
|
|
|
|
case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
|
|
|
|
case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
|
|
|
|
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
|
|
|
|
if (AceHeader->AceFlags & FAILED_ACCESS_ACE_FLAG)
|
|
|
|
Mode = SET_AUDIT_FAILURE;
|
|
|
|
else if (AceHeader->AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
|
|
|
|
Mode = SET_AUDIT_SUCCESS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
static UINT
|
|
|
|
AccpGetAceStructureSize(IN PACE_HEADER AceHeader)
|
|
|
|
{
|
|
|
|
UINT Size = 0;
|
|
|
|
|
|
|
|
switch (AceHeader->AceType)
|
|
|
|
{
|
|
|
|
case ACCESS_ALLOWED_ACE_TYPE:
|
|
|
|
case ACCESS_DENIED_ACE_TYPE:
|
|
|
|
Size = FIELD_OFFSET(ACCESS_ALLOWED_ACE,
|
|
|
|
SidStart);
|
|
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
|
|
|
|
case ACCESS_DENIED_CALLBACK_ACE_TYPE:
|
|
|
|
Size = FIELD_OFFSET(ACCESS_ALLOWED_CALLBACK_ACE,
|
|
|
|
SidStart);
|
|
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
|
|
|
|
case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
|
|
|
|
{
|
|
|
|
PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader;
|
|
|
|
Size = FIELD_OFFSET(ACCESS_ALLOWED_CALLBACK_OBJECT_ACE,
|
|
|
|
ObjectType);
|
|
|
|
if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
|
|
|
|
Size += sizeof(Ace->ObjectType);
|
|
|
|
if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
|
|
|
|
Size += sizeof(Ace->InheritedObjectType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
|
|
|
|
case ACCESS_DENIED_OBJECT_ACE_TYPE:
|
|
|
|
{
|
|
|
|
PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader;
|
|
|
|
Size = FIELD_OFFSET(ACCESS_ALLOWED_OBJECT_ACE,
|
|
|
|
ObjectType);
|
|
|
|
if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
|
|
|
|
Size += sizeof(Ace->ObjectType);
|
|
|
|
if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
|
|
|
|
Size += sizeof(Ace->InheritedObjectType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SYSTEM_AUDIT_ACE_TYPE:
|
|
|
|
Size = FIELD_OFFSET(SYSTEM_AUDIT_ACE,
|
|
|
|
SidStart);
|
|
|
|
break;
|
|
|
|
case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
|
|
|
|
Size = FIELD_OFFSET(SYSTEM_AUDIT_CALLBACK_ACE,
|
|
|
|
SidStart);
|
|
|
|
break;
|
|
|
|
case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
|
|
|
|
{
|
|
|
|
PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader;
|
|
|
|
Size = FIELD_OFFSET(SYSTEM_AUDIT_CALLBACK_OBJECT_ACE,
|
|
|
|
ObjectType);
|
|
|
|
if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
|
|
|
|
Size += sizeof(Ace->ObjectType);
|
|
|
|
if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
|
|
|
|
Size += sizeof(Ace->InheritedObjectType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
|
|
|
|
{
|
|
|
|
PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader;
|
|
|
|
Size = FIELD_OFFSET(SYSTEM_AUDIT_OBJECT_ACE,
|
|
|
|
ObjectType);
|
|
|
|
if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
|
|
|
|
Size += sizeof(Ace->ObjectType);
|
|
|
|
if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
|
|
|
|
Size += sizeof(Ace->InheritedObjectType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PSID
|
|
|
|
AccpGetAceSid(IN PACE_HEADER AceHeader)
|
|
|
|
{
|
|
|
|
return (PSID)((ULONG_PTR)AceHeader + AccpGetAceStructureSize(AceHeader));
|
|
|
|
}
|
|
|
|
|
|
|
|
static ACCESS_MASK
|
|
|
|
AccpGetAceAccessMask(IN PACE_HEADER AceHeader)
|
|
|
|
{
|
|
|
|
return *((PACCESS_MASK)(AceHeader + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-26 21:17:06 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* AccRewriteGetHandleRights EXPORTED
|
|
|
|
*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2006-03-08 19:24:46 +00:00
|
|
|
DWORD WINAPI
|
2005-07-26 21:17:06 +00:00
|
|
|
AccRewriteGetHandleRights(HANDLE handle,
|
|
|
|
SE_OBJECT_TYPE ObjectType,
|
|
|
|
SECURITY_INFORMATION SecurityInfo,
|
|
|
|
PSID* ppsidOwner,
|
|
|
|
PSID* ppsidGroup,
|
|
|
|
PACL* ppDacl,
|
|
|
|
PACL* ppSacl,
|
|
|
|
PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
|
|
|
|
{
|
2006-01-22 03:07:21 +00:00
|
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
2006-01-22 03:27:21 +00:00
|
|
|
ULONG SDSize = 0;
|
2006-01-22 03:07:21 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
DWORD LastErr;
|
2006-01-22 14:03:12 +00:00
|
|
|
DWORD Ret;
|
2006-01-22 03:07:21 +00:00
|
|
|
|
|
|
|
/* save the last error code */
|
|
|
|
LastErr = GetLastError();
|
|
|
|
|
2006-01-22 03:27:21 +00:00
|
|
|
do
|
2006-01-22 03:07:21 +00:00
|
|
|
{
|
2006-01-22 14:03:12 +00:00
|
|
|
Ret = ERROR_SUCCESS;
|
|
|
|
|
2006-01-22 03:27:21 +00:00
|
|
|
/* allocate a buffer large enough to hold the
|
|
|
|
security descriptor we need to return */
|
|
|
|
SDSize += 0x100;
|
2006-01-22 03:53:02 +00:00
|
|
|
if (pSD == NULL)
|
2006-01-22 03:27:21 +00:00
|
|
|
{
|
|
|
|
pSD = LocalAlloc(LMEM_FIXED,
|
|
|
|
(SIZE_T)SDSize);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-01-22 03:50:36 +00:00
|
|
|
PSECURITY_DESCRIPTOR newSD;
|
|
|
|
|
|
|
|
newSD = LocalReAlloc((HLOCAL)pSD,
|
|
|
|
(SIZE_T)SDSize,
|
|
|
|
LMEM_MOVEABLE);
|
|
|
|
if (newSD != NULL)
|
|
|
|
pSD = newSD;
|
2006-01-22 03:27:21 +00:00
|
|
|
}
|
2006-01-22 03:07:21 +00:00
|
|
|
|
2006-01-22 03:27:21 +00:00
|
|
|
if (pSD == NULL)
|
2006-01-22 03:07:21 +00:00
|
|
|
{
|
2006-01-22 03:27:21 +00:00
|
|
|
Ret = GetLastError();
|
2006-01-22 03:07:21 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-01-22 03:27:21 +00:00
|
|
|
/* perform the actual query depending on the object type */
|
|
|
|
switch (ObjectType)
|
2006-01-22 03:07:21 +00:00
|
|
|
{
|
2006-01-22 03:27:21 +00:00
|
|
|
case SE_REGISTRY_KEY:
|
|
|
|
{
|
2006-01-22 14:03:12 +00:00
|
|
|
Ret = (DWORD)RegGetKeySecurity((HKEY)handle,
|
|
|
|
SecurityInfo,
|
|
|
|
pSD,
|
|
|
|
&SDSize);
|
2006-01-22 03:27:21 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SE_FILE_OBJECT:
|
2006-01-22 14:03:12 +00:00
|
|
|
/* FIXME - handle console handles? */
|
2006-01-22 03:27:21 +00:00
|
|
|
case SE_KERNEL_OBJECT:
|
|
|
|
{
|
|
|
|
Status = NtQuerySecurityObject(handle,
|
|
|
|
SecurityInfo,
|
|
|
|
pSD,
|
|
|
|
SDSize,
|
|
|
|
&SDSize);
|
2006-01-22 14:03:12 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Ret = RtlNtStatusToDosError(Status);
|
|
|
|
}
|
2006-01-22 03:27:21 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SE_SERVICE:
|
|
|
|
{
|
2006-01-22 14:03:12 +00:00
|
|
|
if (!QueryServiceObjectSecurity((SC_HANDLE)handle,
|
|
|
|
SecurityInfo,
|
|
|
|
pSD,
|
|
|
|
SDSize,
|
|
|
|
&SDSize))
|
|
|
|
{
|
|
|
|
Ret = GetLastError();
|
|
|
|
}
|
2006-01-22 03:27:21 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SE_WINDOW_OBJECT:
|
|
|
|
{
|
2006-01-22 14:03:12 +00:00
|
|
|
if (!GetUserObjectSecurity(handle,
|
|
|
|
&SecurityInfo,
|
|
|
|
pSD,
|
|
|
|
SDSize,
|
|
|
|
&SDSize))
|
|
|
|
{
|
|
|
|
Ret = GetLastError();
|
|
|
|
}
|
2006-01-22 03:27:21 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
Ret = ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
break;
|
|
|
|
}
|
2006-01-22 03:07:21 +00:00
|
|
|
}
|
|
|
|
|
2006-01-22 03:27:21 +00:00
|
|
|
} while (Ret == ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
|
2006-01-22 03:07:21 +00:00
|
|
|
if (Ret == ERROR_SUCCESS)
|
|
|
|
{
|
2006-01-22 03:50:36 +00:00
|
|
|
BOOL Present, Defaulted;
|
|
|
|
|
|
|
|
if (SecurityInfo & OWNER_SECURITY_INFORMATION && ppsidOwner != NULL)
|
|
|
|
{
|
|
|
|
*ppsidOwner = NULL;
|
|
|
|
if (!GetSecurityDescriptorOwner(pSD,
|
|
|
|
ppsidOwner,
|
|
|
|
&Defaulted))
|
|
|
|
{
|
|
|
|
Ret = GetLastError();
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SecurityInfo & GROUP_SECURITY_INFORMATION && ppsidGroup != NULL)
|
|
|
|
{
|
|
|
|
*ppsidOwner = NULL;
|
|
|
|
if (!GetSecurityDescriptorGroup(pSD,
|
|
|
|
ppsidGroup,
|
|
|
|
&Defaulted))
|
|
|
|
{
|
|
|
|
Ret = GetLastError();
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SecurityInfo & DACL_SECURITY_INFORMATION && ppDacl != NULL)
|
|
|
|
{
|
|
|
|
*ppDacl = NULL;
|
|
|
|
if (!GetSecurityDescriptorDacl(pSD,
|
|
|
|
&Present,
|
|
|
|
ppDacl,
|
|
|
|
&Defaulted))
|
|
|
|
{
|
|
|
|
Ret = GetLastError();
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SecurityInfo & SACL_SECURITY_INFORMATION && ppSacl != NULL)
|
|
|
|
{
|
|
|
|
*ppSacl = NULL;
|
|
|
|
if (!GetSecurityDescriptorSacl(pSD,
|
|
|
|
&Present,
|
|
|
|
ppSacl,
|
|
|
|
&Defaulted))
|
|
|
|
{
|
|
|
|
Ret = GetLastError();
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-22 03:07:21 +00:00
|
|
|
*ppSecurityDescriptor = pSD;
|
|
|
|
}
|
2006-01-22 03:50:36 +00:00
|
|
|
else
|
2006-01-22 03:07:21 +00:00
|
|
|
{
|
2006-01-22 03:50:36 +00:00
|
|
|
Cleanup:
|
|
|
|
if (pSD != NULL)
|
|
|
|
{
|
|
|
|
LocalFree((HLOCAL)pSD);
|
|
|
|
}
|
2006-01-22 03:07:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* restore the last error code */
|
|
|
|
SetLastError(LastErr);
|
|
|
|
|
|
|
|
return Ret;
|
2005-07-26 21:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* AccRewriteSetHandleRights EXPORTED
|
|
|
|
*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2006-03-08 19:24:46 +00:00
|
|
|
DWORD WINAPI
|
2005-07-26 21:17:06 +00:00
|
|
|
AccRewriteSetHandleRights(HANDLE handle,
|
|
|
|
SE_OBJECT_TYPE ObjectType,
|
|
|
|
SECURITY_INFORMATION SecurityInfo,
|
|
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor)
|
|
|
|
{
|
2006-01-22 14:03:12 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
DWORD LastErr;
|
|
|
|
DWORD Ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
/* save the last error code */
|
|
|
|
LastErr = GetLastError();
|
|
|
|
|
|
|
|
/* set the security according to the object type */
|
|
|
|
switch (ObjectType)
|
|
|
|
{
|
|
|
|
case SE_REGISTRY_KEY:
|
|
|
|
{
|
|
|
|
Ret = (DWORD)RegSetKeySecurity((HKEY)handle,
|
|
|
|
SecurityInfo,
|
|
|
|
pSecurityDescriptor);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SE_FILE_OBJECT:
|
|
|
|
/* FIXME - handle console handles? */
|
|
|
|
case SE_KERNEL_OBJECT:
|
|
|
|
{
|
|
|
|
Status = NtSetSecurityObject(handle,
|
|
|
|
SecurityInfo,
|
|
|
|
pSecurityDescriptor);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Ret = RtlNtStatusToDosError(Status);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SE_SERVICE:
|
|
|
|
{
|
|
|
|
if (!SetServiceObjectSecurity((SC_HANDLE)handle,
|
|
|
|
SecurityInfo,
|
|
|
|
pSecurityDescriptor))
|
|
|
|
{
|
|
|
|
Ret = GetLastError();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SE_WINDOW_OBJECT:
|
|
|
|
{
|
|
|
|
if (!SetUserObjectSecurity(handle,
|
|
|
|
&SecurityInfo,
|
|
|
|
pSecurityDescriptor))
|
|
|
|
{
|
|
|
|
Ret = GetLastError();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
Ret = ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* restore the last error code */
|
|
|
|
SetLastError(LastErr);
|
|
|
|
|
|
|
|
return Ret;
|
2005-07-26 21:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-08 19:24:46 +00:00
|
|
|
static DWORD
|
|
|
|
AccpOpenNamedObject(LPWSTR pObjectName,
|
|
|
|
SE_OBJECT_TYPE ObjectType,
|
|
|
|
SECURITY_INFORMATION SecurityInfo,
|
|
|
|
PHANDLE Handle,
|
|
|
|
PHANDLE Handle2,
|
|
|
|
BOOL Write)
|
|
|
|
{
|
|
|
|
LPWSTR lpPath;
|
|
|
|
ACCESS_MASK DesiredAccess = (ACCESS_MASK)0;
|
|
|
|
DWORD Ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
/* determine the required access rights */
|
|
|
|
switch (ObjectType)
|
|
|
|
{
|
|
|
|
case SE_REGISTRY_KEY:
|
|
|
|
case SE_FILE_OBJECT:
|
|
|
|
case SE_KERNEL_OBJECT:
|
|
|
|
case SE_SERVICE:
|
|
|
|
case SE_WINDOW_OBJECT:
|
|
|
|
if (Write)
|
|
|
|
{
|
|
|
|
if (SecurityInfo & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
|
|
|
|
DesiredAccess |= WRITE_OWNER;
|
|
|
|
if (SecurityInfo & DACL_SECURITY_INFORMATION)
|
|
|
|
DesiredAccess |= WRITE_DAC;
|
|
|
|
if (SecurityInfo & SACL_SECURITY_INFORMATION)
|
|
|
|
DesiredAccess |= ACCESS_SYSTEM_SECURITY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (SecurityInfo & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
|
|
|
DACL_SECURITY_INFORMATION))
|
|
|
|
DesiredAccess |= READ_CONTROL;
|
|
|
|
if (SecurityInfo & SACL_SECURITY_INFORMATION)
|
|
|
|
DesiredAccess |= ACCESS_SYSTEM_SECURITY;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* make a copy of the path if we're modifying the string */
|
|
|
|
switch (ObjectType)
|
|
|
|
{
|
|
|
|
case SE_REGISTRY_KEY:
|
|
|
|
case SE_SERVICE:
|
|
|
|
lpPath = (LPWSTR)LocalAlloc(LMEM_FIXED,
|
|
|
|
(wcslen(pObjectName) + 1) * sizeof(WCHAR));
|
|
|
|
if (lpPath == NULL)
|
|
|
|
{
|
|
|
|
Ret = GetLastError();
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
wcscpy(lpPath,
|
|
|
|
pObjectName);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
lpPath = pObjectName;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* open a handle to the path depending on the object type */
|
|
|
|
switch (ObjectType)
|
|
|
|
{
|
|
|
|
case SE_REGISTRY_KEY:
|
|
|
|
{
|
|
|
|
static const struct
|
|
|
|
{
|
|
|
|
HKEY hRootKey;
|
|
|
|
LPCWSTR szRootKey;
|
|
|
|
} AccRegRootKeys[] =
|
|
|
|
{
|
|
|
|
{HKEY_CLASSES_ROOT, L"CLASSES_ROOT"},
|
|
|
|
{HKEY_CURRENT_USER, L"CURRENT_USER"},
|
|
|
|
{HKEY_LOCAL_MACHINE, L"MACHINE"},
|
|
|
|
{HKEY_USERS, L"USERS"},
|
|
|
|
{HKEY_CURRENT_CONFIG, L"CONFIG"},
|
|
|
|
};
|
|
|
|
LPWSTR lpMachineName, lpRootKeyName, lpKeyName;
|
|
|
|
HKEY hRootKey = NULL;
|
|
|
|
UINT i;
|
|
|
|
|
|
|
|
/* parse the registry path */
|
|
|
|
if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
|
|
|
|
{
|
|
|
|
lpMachineName = lpPath;
|
|
|
|
|
|
|
|
lpRootKeyName = wcschr(lpPath + 2,
|
|
|
|
L'\\');
|
|
|
|
if (lpRootKeyName == NULL)
|
|
|
|
goto ParseRegErr;
|
|
|
|
else
|
|
|
|
*(lpRootKeyName++) = L'\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lpMachineName = NULL;
|
|
|
|
lpRootKeyName = lpPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
lpKeyName = wcschr(lpRootKeyName,
|
|
|
|
L'\\');
|
|
|
|
if (lpKeyName != NULL)
|
|
|
|
{
|
|
|
|
*(lpKeyName++) = L'\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0;
|
|
|
|
i != sizeof(AccRegRootKeys) / sizeof(AccRegRootKeys[0]);
|
|
|
|
i++)
|
|
|
|
{
|
|
|
|
if (!wcsicmp(lpRootKeyName,
|
|
|
|
AccRegRootKeys[i].szRootKey))
|
|
|
|
{
|
|
|
|
hRootKey = AccRegRootKeys[i].hRootKey;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hRootKey == NULL)
|
|
|
|
{
|
|
|
|
ParseRegErr:
|
|
|
|
/* FIXME - right error code? */
|
|
|
|
Ret = ERROR_INVALID_PARAMETER;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* open the registry key */
|
|
|
|
if (lpMachineName != NULL)
|
|
|
|
{
|
|
|
|
Ret = RegConnectRegistry(lpMachineName,
|
|
|
|
hRootKey,
|
|
|
|
(PHKEY)Handle2);
|
|
|
|
|
|
|
|
if (Ret != ERROR_SUCCESS)
|
|
|
|
goto Cleanup;
|
|
|
|
|
|
|
|
hRootKey = (HKEY)(*Handle2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ret = RegOpenKeyEx(hRootKey,
|
|
|
|
lpKeyName,
|
|
|
|
0,
|
|
|
|
(REGSAM)DesiredAccess,
|
|
|
|
(PHKEY)Handle);
|
|
|
|
if (Ret != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
if (*Handle2 != NULL)
|
|
|
|
{
|
|
|
|
RegCloseKey((HKEY)(*Handle2));
|
|
|
|
}
|
|
|
|
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SE_SERVICE:
|
|
|
|
{
|
|
|
|
LPWSTR lpServiceName, lpMachineName;
|
|
|
|
|
|
|
|
/* parse the service path */
|
|
|
|
if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
|
|
|
|
{
|
|
|
|
DesiredAccess |= SC_MANAGER_CONNECT;
|
|
|
|
|
|
|
|
lpMachineName = lpPath;
|
|
|
|
|
|
|
|
lpServiceName = wcschr(lpPath + 2,
|
|
|
|
L'\\');
|
|
|
|
if (lpServiceName == NULL)
|
|
|
|
{
|
|
|
|
/* FIXME - right error code? */
|
|
|
|
Ret = ERROR_INVALID_PARAMETER;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*(lpServiceName++) = L'\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lpMachineName = NULL;
|
|
|
|
lpServiceName = lpPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* open the service */
|
|
|
|
*Handle2 = (HANDLE)OpenSCManager(lpMachineName,
|
|
|
|
NULL,
|
|
|
|
(DWORD)DesiredAccess);
|
|
|
|
if (*Handle2 == NULL)
|
|
|
|
{
|
|
|
|
goto FailOpenService;
|
|
|
|
}
|
|
|
|
|
|
|
|
DesiredAccess &= ~SC_MANAGER_CONNECT;
|
|
|
|
*Handle = (HANDLE)OpenService((SC_HANDLE)(*Handle2),
|
|
|
|
lpServiceName,
|
2006-03-09 20:15:11 +00:00
|
|
|
(DWORD)DesiredAccess);
|
2006-03-08 19:24:46 +00:00
|
|
|
if (*Handle == NULL)
|
|
|
|
{
|
|
|
|
if (*Handle2 != NULL)
|
|
|
|
{
|
|
|
|
CloseServiceHandle((SC_HANDLE)(*Handle2));
|
|
|
|
}
|
|
|
|
|
|
|
|
FailOpenService:
|
|
|
|
Ret = GetLastError();
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
Ret = ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (lpPath != NULL)
|
|
|
|
{
|
|
|
|
LocalFree((HLOCAL)lpPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static VOID
|
|
|
|
AccpCloseObjectHandle(SE_OBJECT_TYPE ObjectType,
|
|
|
|
HANDLE Handle,
|
|
|
|
HANDLE Handle2)
|
|
|
|
{
|
|
|
|
ASSERT(Handle != NULL);
|
|
|
|
|
|
|
|
/* close allocated handlees depending on the object type */
|
|
|
|
switch (ObjectType)
|
|
|
|
{
|
|
|
|
case SE_REGISTRY_KEY:
|
|
|
|
RegCloseKey((HKEY)Handle);
|
|
|
|
if (Handle2 != NULL)
|
|
|
|
RegCloseKey((HKEY)Handle2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SE_FILE_OBJECT:
|
|
|
|
case SE_KERNEL_OBJECT:
|
|
|
|
case SE_WINDOW_OBJECT:
|
|
|
|
CloseHandle(Handle);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SE_SERVICE:
|
|
|
|
CloseServiceHandle((SC_HANDLE)Handle);
|
|
|
|
ASSERT(Handle2 != NULL);
|
|
|
|
CloseServiceHandle((SC_HANDLE)Handle2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-26 22:21:02 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* AccRewriteGetNamedRights EXPORTED
|
|
|
|
*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2006-03-08 19:24:46 +00:00
|
|
|
DWORD WINAPI
|
2005-07-26 22:21:02 +00:00
|
|
|
AccRewriteGetNamedRights(LPWSTR pObjectName,
|
|
|
|
SE_OBJECT_TYPE ObjectType,
|
|
|
|
SECURITY_INFORMATION SecurityInfo,
|
|
|
|
PSID* ppsidOwner,
|
|
|
|
PSID* ppsidGroup,
|
|
|
|
PACL* ppDacl,
|
|
|
|
PACL* ppSacl,
|
|
|
|
PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
|
|
|
|
{
|
2006-03-08 19:24:46 +00:00
|
|
|
HANDLE Handle = NULL;
|
|
|
|
HANDLE Handle2 = NULL;
|
|
|
|
DWORD LastErr;
|
|
|
|
DWORD Ret;
|
|
|
|
|
|
|
|
/* save the last error code */
|
|
|
|
LastErr = GetLastError();
|
|
|
|
|
|
|
|
/* create the handle */
|
|
|
|
Ret = AccpOpenNamedObject(pObjectName,
|
|
|
|
ObjectType,
|
|
|
|
SecurityInfo,
|
|
|
|
&Handle,
|
|
|
|
&Handle2,
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
if (Ret == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
ASSERT(Handle != NULL);
|
|
|
|
|
|
|
|
/* perform the operation */
|
|
|
|
Ret = AccRewriteGetHandleRights(Handle,
|
|
|
|
ObjectType,
|
|
|
|
SecurityInfo,
|
|
|
|
ppsidOwner,
|
|
|
|
ppsidGroup,
|
|
|
|
ppDacl,
|
|
|
|
ppSacl,
|
|
|
|
ppSecurityDescriptor);
|
|
|
|
|
|
|
|
/* close opened handles */
|
|
|
|
AccpCloseObjectHandle(ObjectType,
|
|
|
|
Handle,
|
|
|
|
Handle2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* restore the last error code */
|
|
|
|
SetLastError(LastErr);
|
|
|
|
|
|
|
|
return Ret;
|
2005-07-26 22:21:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* AccRewriteSetNamedRights EXPORTED
|
|
|
|
*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2006-03-08 19:24:46 +00:00
|
|
|
DWORD WINAPI
|
2005-07-26 22:21:02 +00:00
|
|
|
AccRewriteSetNamedRights(LPWSTR pObjectName,
|
|
|
|
SE_OBJECT_TYPE ObjectType,
|
|
|
|
SECURITY_INFORMATION SecurityInfo,
|
|
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor)
|
|
|
|
{
|
2006-03-08 19:24:46 +00:00
|
|
|
HANDLE Handle = NULL;
|
|
|
|
HANDLE Handle2 = NULL;
|
|
|
|
DWORD LastErr;
|
|
|
|
DWORD Ret;
|
|
|
|
|
|
|
|
/* save the last error code */
|
|
|
|
LastErr = GetLastError();
|
|
|
|
|
|
|
|
/* create the handle */
|
|
|
|
Ret = AccpOpenNamedObject(pObjectName,
|
|
|
|
ObjectType,
|
|
|
|
SecurityInfo,
|
|
|
|
&Handle,
|
|
|
|
&Handle2,
|
|
|
|
TRUE);
|
|
|
|
|
|
|
|
if (Ret == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
ASSERT(Handle != NULL);
|
|
|
|
|
|
|
|
/* perform the operation */
|
|
|
|
Ret = AccRewriteSetHandleRights(Handle,
|
|
|
|
ObjectType,
|
|
|
|
SecurityInfo,
|
|
|
|
pSecurityDescriptor);
|
|
|
|
|
|
|
|
/* close opened handles */
|
|
|
|
AccpCloseObjectHandle(ObjectType,
|
|
|
|
Handle,
|
|
|
|
Handle2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* restore the last error code */
|
|
|
|
SetLastError(LastErr);
|
|
|
|
|
|
|
|
return Ret;
|
2005-07-26 22:21:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-27 17:20:57 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* AccRewriteSetEntriesInAcl EXPORTED
|
|
|
|
*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2006-03-08 19:24:46 +00:00
|
|
|
DWORD WINAPI
|
2005-07-27 17:20:57 +00:00
|
|
|
AccRewriteSetEntriesInAcl(ULONG cCountOfExplicitEntries,
|
|
|
|
PEXPLICIT_ACCESS_W pListOfExplicitEntries,
|
|
|
|
PACL OldAcl,
|
|
|
|
PACL* NewAcl)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-27 18:24:18 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* AccRewriteSetEntriesInAcl EXPORTED
|
|
|
|
*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2006-03-08 19:24:46 +00:00
|
|
|
DWORD WINAPI
|
2005-07-27 18:24:18 +00:00
|
|
|
AccGetInheritanceSource(LPWSTR pObjectName,
|
|
|
|
SE_OBJECT_TYPE ObjectType,
|
|
|
|
SECURITY_INFORMATION SecurityInfo,
|
|
|
|
BOOL Container,
|
|
|
|
GUID** pObjectClassGuids,
|
|
|
|
DWORD GuidCount,
|
|
|
|
PACL pAcl,
|
|
|
|
PFN_OBJECT_MGR_FUNCTS pfnArray,
|
|
|
|
PGENERIC_MAPPING pGenericMapping,
|
|
|
|
PINHERITED_FROMW pInheritArray)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* AccFreeIndexArray EXPORTED
|
|
|
|
*
|
2006-03-08 19:24:46 +00:00
|
|
|
* @implemented
|
2005-07-27 18:24:18 +00:00
|
|
|
*/
|
2006-03-08 19:24:46 +00:00
|
|
|
DWORD WINAPI
|
2005-07-27 18:24:18 +00:00
|
|
|
AccFreeIndexArray(PINHERITED_FROMW pInheritArray,
|
|
|
|
USHORT AceCnt,
|
|
|
|
PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL)
|
|
|
|
{
|
2006-03-08 19:24:46 +00:00
|
|
|
UNREFERENCED_PARAMETER(pfnArray);
|
|
|
|
|
|
|
|
while (AceCnt != 0)
|
|
|
|
{
|
|
|
|
if (pInheritArray->AncestorName != NULL)
|
|
|
|
{
|
|
|
|
LocalFree((HLOCAL)pInheritArray->AncestorName);
|
|
|
|
pInheritArray->AncestorName = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pInheritArray++;
|
|
|
|
AceCnt--;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
2005-07-27 18:24:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-27 20:24:11 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* AccRewriteGetExplicitEntriesFromAcl EXPORTED
|
|
|
|
*
|
2006-03-09 20:15:11 +00:00
|
|
|
* @implemented
|
2005-07-27 20:24:11 +00:00
|
|
|
*/
|
2006-03-08 19:24:46 +00:00
|
|
|
DWORD WINAPI
|
2005-07-27 20:24:11 +00:00
|
|
|
AccRewriteGetExplicitEntriesFromAcl(PACL pacl,
|
|
|
|
PULONG pcCountOfExplicitEntries,
|
|
|
|
PEXPLICIT_ACCESS_W* pListOfExplicitEntries)
|
|
|
|
{
|
2006-03-09 20:15:11 +00:00
|
|
|
PACE_HEADER AceHeader;
|
|
|
|
PSID Sid, SidTarget;
|
|
|
|
SIZE_T Size;
|
|
|
|
PEXPLICIT_ACCESS_W peaw;
|
|
|
|
DWORD LastErr, SidLen;
|
|
|
|
DWORD AceIndex = 0;
|
|
|
|
DWORD ErrorCode = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
/* save the last error code */
|
|
|
|
LastErr = GetLastError();
|
|
|
|
|
|
|
|
if (pacl != NULL)
|
|
|
|
{
|
|
|
|
if (pacl->AceCount != 0)
|
|
|
|
{
|
|
|
|
Size = (SIZE_T)pacl->AceCount * sizeof(EXPLICIT_ACCESS_W);
|
|
|
|
|
|
|
|
/* calculate the space needed */
|
|
|
|
while (GetAce(pacl,
|
|
|
|
AceIndex,
|
|
|
|
(LPVOID*)&AceHeader))
|
|
|
|
{
|
|
|
|
Sid = AccpGetAceSid(AceHeader);
|
|
|
|
Size += GetLengthSid(Sid);
|
|
|
|
/* FIXME - take size of opaque data in account? */
|
|
|
|
AceIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(pacl->AceCount == AceIndex);
|
|
|
|
|
|
|
|
/* allocate the array */
|
|
|
|
peaw = (PEXPLICIT_ACCESS_W)LocalAlloc(LMEM_FIXED,
|
|
|
|
Size);
|
|
|
|
if (peaw != NULL)
|
|
|
|
{
|
|
|
|
AceIndex = 0;
|
|
|
|
SidTarget = (PSID)(peaw + pacl->AceCount);
|
|
|
|
|
|
|
|
/* initialize the array */\
|
|
|
|
while (GetAce(pacl,
|
|
|
|
AceIndex,
|
|
|
|
(LPVOID*)&AceHeader))
|
|
|
|
{
|
|
|
|
Sid = AccpGetAceSid(AceHeader);
|
|
|
|
SidLen = GetLengthSid(Sid);
|
|
|
|
|
|
|
|
peaw[AceIndex].grfAccessPermissions = AccpGetAceAccessMask(AceHeader);
|
|
|
|
peaw[AceIndex].grfAccessMode = AccpGetAceAccessMode(AceHeader);
|
|
|
|
peaw[AceIndex].grfInheritance = AceHeader->AceFlags & VALID_INHERIT_FLAGS;
|
|
|
|
|
|
|
|
if (CopySid(SidLen,
|
|
|
|
SidTarget,
|
|
|
|
Sid))
|
|
|
|
{
|
|
|
|
BuildTrusteeWithSid(&peaw[AceIndex].Trustee,
|
|
|
|
SidTarget);
|
|
|
|
SidTarget = (PSID)((ULONG_PTR)SidTarget + SidLen);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* copying the SID failed, treat it as an fatal error... */
|
|
|
|
ErrorCode = GetLastError();
|
|
|
|
|
|
|
|
/* free allocated resources */
|
|
|
|
LocalFree(peaw);
|
|
|
|
peaw = NULL;
|
|
|
|
AceIndex = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
AceIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pcCountOfExplicitEntries = AceIndex;
|
|
|
|
*pListOfExplicitEntries = peaw;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*pcCountOfExplicitEntries = 0;
|
|
|
|
*pListOfExplicitEntries = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* restore the last error code */
|
|
|
|
SetLastError(LastErr);
|
|
|
|
|
|
|
|
return ErrorCode;
|
2005-07-27 20:24:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-27 23:11:38 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* AccTreeResetNamedSecurityInfo EXPORTED
|
|
|
|
*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2006-03-08 19:24:46 +00:00
|
|
|
DWORD WINAPI
|
2005-07-27 23:11:38 +00:00
|
|
|
AccTreeResetNamedSecurityInfo(LPWSTR pObjectName,
|
|
|
|
SE_OBJECT_TYPE ObjectType,
|
|
|
|
SECURITY_INFORMATION SecurityInfo,
|
|
|
|
PSID pOwner,
|
|
|
|
PSID pGroup,
|
|
|
|
PACL pDacl,
|
|
|
|
PACL pSacl,
|
|
|
|
BOOL KeepExplicit,
|
|
|
|
FN_PROGRESSW fnProgress,
|
|
|
|
PROG_INVOKE_SETTING ProgressInvokeSetting,
|
|
|
|
PVOID Args)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-08 19:24:46 +00:00
|
|
|
BOOL WINAPI
|
2005-07-26 21:17:06 +00:00
|
|
|
DllMain(IN HINSTANCE hinstDLL,
|
|
|
|
IN DWORD dwReason,
|
|
|
|
IN LPVOID lpvReserved)
|
|
|
|
{
|
|
|
|
switch (dwReason)
|
|
|
|
{
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
hDllInstance = hinstDLL;
|
2006-01-22 14:03:12 +00:00
|
|
|
DisableThreadLibraryCalls(hinstDLL);
|
2005-07-26 21:17:06 +00:00
|
|
|
break;
|
2006-01-22 14:03:12 +00:00
|
|
|
|
2005-07-26 21:17:06 +00:00
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|