Synchronize with trunk's revision r57599.

svn path=/branches/ros-csrss/; revision=57600
This commit is contained in:
Hermès Bélusca-Maïto 2012-10-23 19:54:03 +00:00
commit aab393ca70
36 changed files with 1985 additions and 571 deletions

View file

@ -1221,6 +1221,7 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olecli32",0x0
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olesvr32",0x00000000,"olesvr32.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olethk32",0x00000000,"olethk32.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","rpcrt4",0x00000000,"rpcrt4.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","setupapi",0x00000000,"setupapi.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","shell32",0x00000000,"shell32.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","url",0x00000000,"url.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","urlmon",0x00000000,"urlmon.dll"

View file

@ -776,6 +776,7 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olecli32",0x0
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olesvr32",0x00000000,"olesvr32.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olethk32",0x00000000,"olethk32.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","rpcrt4",0x00000000,"rpcrt4.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","setupapi",0x00000000,"setupapi.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","shell32",0x00000000,"shell32.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","url",0x00000000,"url.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","urlmon",0x00000000,"urlmon.dll"

View file

@ -1221,6 +1221,7 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olecli32",0x0
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olesvr32",0x00000000,"olesvr32.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olethk32",0x00000000,"olethk32.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","rpcrt4",0x00000000,"rpcrt4.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","setupapi",0x00000000,"setupapi.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","shell32",0x00000000,"shell32.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","url",0x00000000,"url.dll"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","urlmon",0x00000000,"urlmon.dll"

View file

@ -13,11 +13,11 @@ spec2def(lsasrv.dll lsasrv.spec ADD_IMPORTLIB)
list(APPEND SOURCE
authport.c
database.c
lookup.c
lsarpc.c
lsasrv.c
policy.c
privileges.c
sids.c
lsasrv.rc
${CMAKE_CURRENT_BINARY_DIR}/lsasrv_stubs.c
${CMAKE_CURRENT_BINARY_DIR}/lsasrv.def

View file

@ -1,7 +1,7 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: Local Security Authority (LSA) Server
* FILE: reactos/dll/win32/lsasrv/sids.c
* FILE: reactos/dll/win32/lsasrv/lookup.c
* PURPOSE: Sid / Name lookup functions
*
* PROGRAMMERS: Eric Kohl
@ -72,8 +72,8 @@ typedef struct _WELL_KNOWN_SID
{
LIST_ENTRY ListEntry;
PSID Sid;
UNICODE_STRING Name;
UNICODE_STRING Domain;
UNICODE_STRING AccountName;
UNICODE_STRING DomainName;
SID_NAME_USE Use;
} WELL_KNOWN_SID, *PWELL_KNOWN_SID;
@ -202,8 +202,8 @@ BOOLEAN
LsapCreateSid(PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
UCHAR SubAuthorityCount,
PULONG SubAuthorities,
PWSTR Name,
PWSTR Domain,
PWSTR AccountName,
PWSTR DomainName,
SID_NAME_USE Use)
{
PWELL_KNOWN_SID SidEntry;
@ -235,11 +235,11 @@ LsapCreateSid(PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
*p = SubAuthorities[i];
}
RtlInitUnicodeString(&SidEntry->Name,
Name);
RtlInitUnicodeString(&SidEntry->AccountName,
AccountName);
RtlInitUnicodeString(&SidEntry->Domain,
Domain);
RtlInitUnicodeString(&SidEntry->DomainName,
DomainName);
SidEntry->Use = Use;
@ -472,6 +472,13 @@ LsapInitSids(VOID)
L"NT AUTHORITY",
SidTypeWellKnownGroup);
LsapCreateSid(&NtAuthority,
1,
SubAuthorities,
L"LOCALSERVICE",
L"NT AUTHORITY",
SidTypeWellKnownGroup);
/* Network Service Sid */
SubAuthorities[0] = SECURITY_NETWORK_SERVICE_RID;
LsapCreateSid(&NtAuthority,
@ -481,6 +488,13 @@ LsapInitSids(VOID)
L"NT AUTHORITY",
SidTypeWellKnownGroup);
LsapCreateSid(&NtAuthority,
1,
SubAuthorities,
L"NETWORKSERVICE",
L"NT AUTHORITY",
SidTypeWellKnownGroup);
/* Builtin Domain Sid */
SubAuthorities[0] = SECURITY_BUILTIN_DOMAIN_RID;
LsapCreateSid(&NtAuthority,
@ -653,7 +667,7 @@ LsapLookupWellKnownSid(PSID Sid)
PWELL_KNOWN_SID
LsapLookupWellKnownName(PUNICODE_STRING Name)
LsapLookupIsolatedWellKnownName(PUNICODE_STRING AccountName)
{
PLIST_ENTRY ListEntry;
PWELL_KNOWN_SID Ptr;
@ -664,7 +678,33 @@ LsapLookupWellKnownName(PUNICODE_STRING Name)
Ptr = CONTAINING_RECORD(ListEntry,
WELL_KNOWN_SID,
ListEntry);
if (RtlEqualUnicodeString(Name, &Ptr->Name, TRUE))
if (RtlEqualUnicodeString(AccountName, &Ptr->AccountName, TRUE))
{
return Ptr;
}
ListEntry = ListEntry->Flink;
}
return NULL;
}
PWELL_KNOWN_SID
LsapLookupFullyQualifiedWellKnownName(PUNICODE_STRING AccountName,
PUNICODE_STRING DomainName)
{
PLIST_ENTRY ListEntry;
PWELL_KNOWN_SID Ptr;
ListEntry = WellKnownSidListHead.Flink;
while (ListEntry != &WellKnownSidListHead)
{
Ptr = CONTAINING_RECORD(ListEntry,
WELL_KNOWN_SID,
ListEntry);
if (RtlEqualUnicodeString(AccountName, &Ptr->AccountName, TRUE) &&
RtlEqualUnicodeString(DomainName, &Ptr->DomainName, TRUE))
{
return Ptr;
}
@ -975,6 +1015,37 @@ CreateDomainSidFromAccountSid(PSID AccountSid)
}
static PSID
LsapCopySid(PSID SrcSid)
{
UCHAR RidCount;
PSID DstSid;
ULONG i;
ULONG DstSidSize;
PULONG p, q;
RidCount = *RtlSubAuthorityCountSid(SrcSid);
DstSidSize = RtlLengthRequiredSid(RidCount);
DstSid = MIDL_user_allocate(DstSidSize);
if (DstSid == NULL)
return NULL;
RtlInitializeSid(DstSid,
RtlIdentifierAuthoritySid(SrcSid),
RidCount);
for (i = 0; i < (ULONG)RidCount; i++)
{
p = RtlSubAuthoritySid(SrcSid, i);
q = RtlSubAuthoritySid(DstSid, i);
*q = *p;
}
return DstSid;
}
static
NTSTATUS
LsapLookupIsolatedNames(DWORD Count,
@ -1004,18 +1075,24 @@ LsapLookupIsolatedNames(DWORD Count,
TRACE("Mapping name: %wZ\n", &AccountNames[i]);
/* Look-up all well-known names */
ptr = LsapLookupWellKnownName((PUNICODE_STRING)&AccountNames[i]);
ptr = LsapLookupIsolatedWellKnownName((PUNICODE_STRING)&AccountNames[i]);
if (ptr != NULL)
{
SidsBuffer[i].Use = ptr->Use;
SidsBuffer[i].Sid = ptr->Sid;
SidsBuffer[i].Sid = LsapCopySid(ptr->Sid);
if (SidsBuffer[i].Sid == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
SidsBuffer[i].DomainIndex = -1;
SidsBuffer[i].Flags = 0;
if (ptr->Use == SidTypeDomain)
{
Status = LsapAddDomainToDomainsList(DomainsBuffer,
&ptr->Name,
&ptr->AccountName,
ptr->Sid,
&DomainIndex);
if (!NT_SUCCESS(Status))
@ -1025,11 +1102,11 @@ LsapLookupIsolatedNames(DWORD Count,
}
else
{
ptr2= LsapLookupWellKnownName(&ptr->Domain);
ptr2= LsapLookupIsolatedWellKnownName(&ptr->DomainName);
if (ptr2 != NULL)
{
Status = LsapAddDomainToDomainsList(DomainsBuffer,
&ptr2->Name,
&ptr2->AccountName,
ptr2->Sid,
&DomainIndex);
if (!NT_SUCCESS(Status))
@ -1072,7 +1149,13 @@ LsapLookupIsolatedNames(DWORD Count,
if (RtlEqualUnicodeString((PUNICODE_STRING)&AccountNames[i], &BuiltinDomainName, TRUE))
{
SidsBuffer[i].Use = SidTypeDomain;
SidsBuffer[i].Sid = BuiltinDomainSid;
SidsBuffer[i].Sid = LsapCopySid(BuiltinDomainSid);
if (SidsBuffer[i].Sid == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
SidsBuffer[i].DomainIndex = -1;
SidsBuffer[i].Flags = 0;
@ -1093,7 +1176,12 @@ LsapLookupIsolatedNames(DWORD Count,
if (RtlEqualUnicodeString((PUNICODE_STRING)&AccountNames[i], &AccountDomainName, TRUE))
{
SidsBuffer[i].Use = SidTypeDomain;
SidsBuffer[i].Sid = AccountDomainSid;
SidsBuffer[i].Sid = LsapCopySid(AccountDomainSid);
if (SidsBuffer[i].Sid == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
SidsBuffer[i].DomainIndex = -1;
SidsBuffer[i].Flags = 0;
@ -1183,7 +1271,10 @@ LsapLookupIsolatedBuiltinNames(DWORD Count,
SidsBuffer[i].Sid = CreateSidFromSidAndRid(BuiltinDomainSid,
RelativeIds.Element[0]);
if (SidsBuffer[i].Sid == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
SidsBuffer[i].DomainIndex = -1;
SidsBuffer[i].Flags = 0;
@ -1278,7 +1369,10 @@ LsapLookupIsolatedAccountNames(DWORD Count,
SidsBuffer[i].Sid = CreateSidFromSidAndRid(AccountDomainSid,
RelativeIds.Element[0]);
if (SidsBuffer[i].Sid == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
SidsBuffer[i].DomainIndex = -1;
SidsBuffer[i].Flags = 0;
@ -1310,6 +1404,114 @@ done:
}
static
NTSTATUS
LsapLookupFullyQualifiedWellKnownNames(DWORD Count,
PRPC_UNICODE_STRING DomainNames,
PRPC_UNICODE_STRING AccountNames,
PLSAPR_REFERENCED_DOMAIN_LIST DomainsBuffer,
PLSAPR_TRANSLATED_SID_EX2 SidsBuffer,
PULONG Mapped)
{
UNICODE_STRING EmptyDomainName = RTL_CONSTANT_STRING(L"");
PWELL_KNOWN_SID ptr, ptr2;
PSID DomainSid;
ULONG DomainIndex;
ULONG i;
NTSTATUS Status = STATUS_SUCCESS;
for (i = 0; i < Count; i++)
{
/* Ignore names which were already mapped */
if (SidsBuffer[i].Use != SidTypeUnknown)
continue;
/* Ignore isolated account names */
if (DomainNames[i].Length == 0)
continue;
TRACE("Mapping name: %wZ\\%wZ\n", &DomainNames[i], &AccountNames[i]);
/* Look-up all well-known names */
ptr = LsapLookupFullyQualifiedWellKnownName((PUNICODE_STRING)&AccountNames[i],
(PUNICODE_STRING)&DomainNames[i]);
if (ptr != NULL)
{
TRACE("Found it! (%wZ\\%wZ)\n", &ptr->DomainName, &ptr->AccountName);
SidsBuffer[i].Use = ptr->Use;
SidsBuffer[i].Sid = LsapCopySid(ptr->Sid);
if (SidsBuffer[i].Sid == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
SidsBuffer[i].DomainIndex = -1;
SidsBuffer[i].Flags = 0;
if (ptr->Use == SidTypeDomain)
{
Status = LsapAddDomainToDomainsList(DomainsBuffer,
&ptr->AccountName,
ptr->Sid,
&DomainIndex);
if (!NT_SUCCESS(Status))
goto done;
SidsBuffer[i].DomainIndex = DomainIndex;
}
else
{
ptr2= LsapLookupIsolatedWellKnownName(&ptr->DomainName);
if (ptr2 != NULL)
{
Status = LsapAddDomainToDomainsList(DomainsBuffer,
&ptr2->AccountName,
ptr2->Sid,
&DomainIndex);
if (!NT_SUCCESS(Status))
goto done;
SidsBuffer[i].DomainIndex = DomainIndex;
}
else
{
DomainSid = CreateDomainSidFromAccountSid(ptr->Sid);
if (DomainSid == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
Status = LsapAddDomainToDomainsList(DomainsBuffer,
&EmptyDomainName,
DomainSid,
&DomainIndex);
if (DomainSid != NULL)
{
MIDL_user_free(DomainSid);
DomainSid = NULL;
}
if (!NT_SUCCESS(Status))
goto done;
SidsBuffer[i].DomainIndex = DomainIndex;
}
}
(*Mapped)++;
continue;
}
}
done:
return Status;
}
static
NTSTATUS
LsapLookupBuiltinNames(DWORD Count,
@ -1359,6 +1561,8 @@ LsapLookupBuiltinNames(DWORD Count,
if (!RtlEqualUnicodeString((PUNICODE_STRING)&DomainNames[i], &BuiltinDomainName, TRUE))
continue;
TRACE("Mapping name: %wZ\\%wZ\n", &DomainNames[i], &AccountNames[i]);
Status = SamrLookupNamesInDomain(DomainHandle,
1,
&AccountNames[i],
@ -1370,7 +1574,10 @@ LsapLookupBuiltinNames(DWORD Count,
SidsBuffer[i].Sid = CreateSidFromSidAndRid(BuiltinDomainSid,
RelativeIds.Element[0]);
if (SidsBuffer[i].Sid == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
SidsBuffer[i].DomainIndex = -1;
SidsBuffer[i].Flags = 0;
@ -1451,6 +1658,8 @@ LsapLookupAccountNames(DWORD Count,
if (!RtlEqualUnicodeString((PUNICODE_STRING)&DomainNames[i], &AccountDomainName, TRUE))
continue;
TRACE("Mapping name: %wZ\\%wZ\n", &DomainNames[i], &AccountNames[i]);
Status = SamrLookupNamesInDomain(DomainHandle,
1,
&AccountNames[i],
@ -1462,7 +1671,10 @@ LsapLookupAccountNames(DWORD Count,
SidsBuffer[i].Sid = CreateSidFromSidAndRid(AccountDomainSid,
RelativeIds.Element[0]);
if (SidsBuffer[i].Sid == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
SidsBuffer[i].DomainIndex = -1;
SidsBuffer[i].Flags = 0;
@ -1509,13 +1721,10 @@ LsapLookupNames(DWORD Count,
PRPC_UNICODE_STRING DomainNames = NULL;
PRPC_UNICODE_STRING AccountNames = NULL;
ULONG SidsBufferLength;
// ULONG DomainIndex;
ULONG i;
ULONG Mapped = 0;
NTSTATUS Status = STATUS_SUCCESS;
// PWELL_KNOWN_SID ptr, ptr2;
//TRACE("()\n");
TranslatedSids->Entries = 0;
@ -1621,7 +1830,22 @@ LsapLookupNames(DWORD Count,
if (Mapped == Count)
goto done;
Status = LsapLookupFullyQualifiedWellKnownNames(Count,
DomainNames,
AccountNames,
DomainsBuffer,
SidsBuffer,
&Mapped);
if (!NT_SUCCESS(Status) &&
Status != STATUS_NONE_MAPPED &&
Status != STATUS_SOME_NOT_MAPPED)
{
TRACE("LsapLookupFullyQualifiedWellKnownNames failed! (Status %lx)\n", Status);
goto done;
}
if (Mapped == Count)
goto done;
Status = LsapLookupBuiltinNames(Count,
DomainNames,
@ -1755,16 +1979,22 @@ LsapLookupWellKnownSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
NamesBuffer[i].Use = ptr->Use;
NamesBuffer[i].Flags = 0;
NamesBuffer[i].Name.Buffer = MIDL_user_allocate(ptr->Name.MaximumLength);
NamesBuffer[i].Name.Length = ptr->Name.Length;
NamesBuffer[i].Name.MaximumLength = ptr->Name.MaximumLength;
RtlCopyMemory(NamesBuffer[i].Name.Buffer, ptr->Name.Buffer, ptr->Name.MaximumLength);
NamesBuffer[i].Name.Length = ptr->AccountName.Length;
NamesBuffer[i].Name.MaximumLength = ptr->AccountName.MaximumLength;
NamesBuffer[i].Name.Buffer = MIDL_user_allocate(ptr->AccountName.MaximumLength);
if (NamesBuffer[i].Name.Buffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
ptr2= LsapLookupWellKnownName(&ptr->Domain);
RtlCopyMemory(NamesBuffer[i].Name.Buffer, ptr->AccountName.Buffer, ptr->AccountName.MaximumLength);
ptr2= LsapLookupIsolatedWellKnownName(&ptr->DomainName);
if (ptr2 != NULL)
{
Status = LsapAddDomainToDomainsList(DomainsBuffer,
&ptr2->Name,
&ptr2->AccountName,
ptr2->Sid,
&DomainIndex);
if (!NT_SUCCESS(Status))
@ -2062,82 +2292,6 @@ done:
}
static NTSTATUS
LsapLookupUnknownSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
PLSAPR_TRANSLATED_NAME_EX NamesBuffer,
PLSAPR_REFERENCED_DOMAIN_LIST DomainsBuffer,
PULONG Mapped)
{
SID_IDENTIFIER_AUTHORITY IdentifierAuthority = {SECURITY_NT_AUTHORITY};
static const UNICODE_STRING DomainName = RTL_CONSTANT_STRING(L"UNKNOWN");
static const UNICODE_STRING AdminName = RTL_CONSTANT_STRING(L"Test");
PSID AdminsSid = NULL;
LPWSTR SidString = NULL;
ULONG SidLength;
ULONG DomainIndex;
ULONG i;
NTSTATUS Status;
Status = RtlAllocateAndInitializeSid(&IdentifierAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdminsSid);
if (!NT_SUCCESS(Status))
goto done;
SidLength = RtlLengthSid(AdminsSid);
for (i = 0; i < SidEnumBuffer->Entries; i++)
{
/* Ignore SIDs which are already mapped */
if (NamesBuffer[i].Use != SidTypeUnknown)
continue;
ConvertSidToStringSidW(SidEnumBuffer->SidInfo[i].Sid, &SidString);
TRACE("Mapping SID: %S\n", SidString);
LocalFree(SidString);
SidString = NULL;
/* Hack: Map the SID to the Admin Account if it is not a well-known SID */
NamesBuffer[i].Use = SidTypeUser;
NamesBuffer[i].Flags = 0;
NamesBuffer[i].Name.Length = AdminName.Length;
NamesBuffer[i].Name.MaximumLength = AdminName.MaximumLength;
NamesBuffer[i].Name.Buffer = MIDL_user_allocate(AdminName.MaximumLength);
if (NamesBuffer[i].Name.Buffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
RtlCopyMemory(NamesBuffer[i].Name.Buffer, AdminName.Buffer, AdminName.MaximumLength);
Status = LsapAddDomainToDomainsList(DomainsBuffer,
(PUNICODE_STRING)&DomainName,
AdminsSid,
&DomainIndex);
if (!NT_SUCCESS(Status))
goto done;
NamesBuffer[i].DomainIndex = DomainIndex;
TRACE("Mapped to: %wZ\n", &NamesBuffer[i].Name);
(*Mapped)++;
}
done:
if (AdminsSid != NULL)
RtlFreeSid(AdminsSid);
return Status;
}
NTSTATUS
LsapLookupSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains,
@ -2229,16 +2383,6 @@ LsapLookupSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
if (Mapped == SidEnumBuffer->Entries)
goto done;
/* Map unknown SIDs */
Status = LsapLookupUnknownSids(SidEnumBuffer,
NamesBuffer,
DomainsBuffer,
&Mapped);
if (!NT_SUCCESS(Status) &&
Status != STATUS_NONE_MAPPED &&
Status != STATUS_SOME_NOT_MAPPED)
goto done;
done:
TRACE("done Status: %lx Mapped: %lu\n", Status, Mapped);

View file

@ -118,6 +118,32 @@ LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject,
LPVOID AttributeData,
ULONG AttributeSize);
/* lookup.c */
NTSTATUS
LsapInitSids(VOID);
ULONG
LsapGetRelativeIdFromSid(PSID Sid);
NTSTATUS
LsapLookupNames(DWORD Count,
PRPC_UNICODE_STRING Names,
PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains,
PLSAPR_TRANSLATED_SIDS_EX2 TranslatedSids,
LSAP_LOOKUP_LEVEL LookupLevel,
DWORD *MappedCount,
DWORD LookupOptions,
DWORD ClientRevision);
NTSTATUS
LsapLookupSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains,
PLSAPR_TRANSLATED_NAMES_EX TranslatedNames,
LSAP_LOOKUP_LEVEL LookupLevel,
DWORD *MappedCount,
DWORD LookupOptions,
DWORD ClientRevision);
/* lsarpc.c */
VOID
LsarStartRpcServer(VOID);
@ -201,30 +227,4 @@ LsarpEnumeratePrivileges(DWORD *EnumerationContext,
PLSAPR_PRIVILEGE_ENUM_BUFFER EnumerationBuffer,
DWORD PreferedMaximumLength);
/* sids.h */
NTSTATUS
LsapInitSids(VOID);
ULONG
LsapGetRelativeIdFromSid(PSID Sid);
NTSTATUS
LsapLookupNames(DWORD Count,
PRPC_UNICODE_STRING Names,
PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains,
PLSAPR_TRANSLATED_SIDS_EX2 TranslatedSids,
LSAP_LOOKUP_LEVEL LookupLevel,
DWORD *MappedCount,
DWORD LookupOptions,
DWORD ClientRevision);
NTSTATUS
LsapLookupSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains,
PLSAPR_TRANSLATED_NAMES_EX TranslatedNames,
LSAP_LOOKUP_LEVEL LookupLevel,
DWORD *MappedCount,
DWORD LookupOptions,
DWORD ClientRevision);
/* EOF */

View file

@ -128,6 +128,66 @@ SamAddMemberToAlias(IN SAM_HANDLE AliasHandle,
}
NTSTATUS
NTAPI
SamAddMemberToGroup(IN SAM_HANDLE GroupHandle,
IN ULONG MemberId,
IN ULONG Attributes)
{
NTSTATUS Status;
TRACE("SamAddMemberToGroup(%p %lu %lx)",
GroupHandle, MemberId, Attributes);
RpcTryExcept
{
Status = SamrAddMemberToGroup((SAMPR_HANDLE)GroupHandle,
MemberId,
Attributes);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamAddMultipleMembersToAlias(IN SAM_HANDLE AliasHandle,
IN PSID *MemberIds,
IN ULONG MemberCount)
{
SAMPR_PSID_ARRAY Buffer;
NTSTATUS Status;
TRACE("SamAddMultipleMembersToAlias(%p %p %lu)\n",
AliasHandle, MemberIds, MemberCount);
if (MemberIds == NULL)
return STATUS_INVALID_PARAMETER_2;
Buffer.Count = MemberCount;
Buffer.Sids = (PSAMPR_SID_INFORMATION)MemberIds;
RpcTryExcept
{
Status = SamrAddMultipleMembersToAlias((SAMPR_HANDLE)AliasHandle,
&Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamCloseHandle(IN SAM_HANDLE SamHandle)
@ -320,6 +380,90 @@ SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
}
NTSTATUS
NTAPI
SamDeleteAlias(IN SAM_HANDLE AliasHandle)
{
SAMPR_HANDLE LocalAliasHandle;
NTSTATUS Status;
TRACE("SamDeleteAlias(%p)\n", AliasHandle);
LocalAliasHandle = (SAMPR_HANDLE)AliasHandle;
if (LocalAliasHandle == NULL)
return STATUS_INVALID_HANDLE;
RpcTryExcept
{
Status = SamrDeleteAlias(&LocalAliasHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamDeleteGroup(IN SAM_HANDLE GroupHandle)
{
SAMPR_HANDLE LocalGroupHandle;
NTSTATUS Status;
TRACE("SamDeleteGroup(%p)\n", GroupHandle);
LocalGroupHandle = (SAMPR_HANDLE)GroupHandle;
if (LocalGroupHandle == NULL)
return STATUS_INVALID_HANDLE;
RpcTryExcept
{
Status = SamrDeleteGroup(&LocalGroupHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamDeleteUser(IN SAM_HANDLE UserHandle)
{
SAMPR_HANDLE LocalUserHandle;
NTSTATUS Status;
TRACE("SamDeleteUser(%p)\n", UserHandle);
LocalUserHandle = (SAMPR_HANDLE)UserHandle;
if (LocalUserHandle == NULL)
return STATUS_INVALID_HANDLE;
RpcTryExcept
{
Status = SamrDeleteUser(&LocalUserHandle);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamEnumerateAliasesInDomain(IN SAM_HANDLE DomainHandle,
@ -577,6 +721,50 @@ SamGetAliasMembership(IN SAM_HANDLE DomainHandle,
}
NTSTATUS
NTAPI
SamGetGroupsForUser(IN SAM_HANDLE UserHandle,
OUT PGROUP_MEMBERSHIP *Groups,
OUT PULONG MembershipCount)
{
PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL;
NTSTATUS Status;
TRACE("SamGetGroupsForUser(%p %p %p)\n",
UserHandle, Groups, MembershipCount);
RpcTryExcept
{
Status = SamrGetGroupsForUser((SAMPR_HANDLE)UserHandle,
&GroupsBuffer);
if (NT_SUCCESS(Status))
{
*Groups = GroupsBuffer->Groups;
*MembershipCount = GroupsBuffer->MembershipCount;
MIDL_user_free(GroupsBuffer);
}
else
{
if (GroupsBuffer != NULL)
{
if (GroupsBuffer->Groups != NULL)
MIDL_user_free(GroupsBuffer->Groups);
MIDL_user_free(GroupsBuffer);
}
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
@ -619,6 +807,55 @@ SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
}
NTSTATUS
NTAPI
SamGetMembersInGroup(IN SAM_HANDLE GroupHandle,
OUT PULONG *MemberIds,
OUT PULONG *Attributes,
OUT PULONG MemberCount)
{
PSAMPR_GET_MEMBERS_BUFFER MembersBuffer = NULL;
NTSTATUS Status;
TRACE("SamGetMembersInGroup(%p %p %p %p)\n",
GroupHandle, MemberIds, Attributes, MemberCount);
RpcTryExcept
{
Status = SamrGetMembersInGroup((SAMPR_HANDLE)GroupHandle,
&MembersBuffer);
if (NT_SUCCESS(Status))
{
*MemberIds = MembersBuffer->Members;
*Attributes = MembersBuffer->Attributes;
*MemberCount = MembersBuffer->MemberCount;
MIDL_user_free(MembersBuffer);
}
else
{
if (MembersBuffer != NULL)
{
if (MembersBuffer->Members != NULL)
MIDL_user_free(MembersBuffer->Members);
if (MembersBuffer->Attributes != NULL)
MIDL_user_free(MembersBuffer->Attributes);
MIDL_user_free(MembersBuffer);
}
}
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
@ -1057,6 +1294,161 @@ SamQueryInformationUser(IN SAM_HANDLE UserHandle,
}
NTSTATUS
NTAPI
SamQuerySecurityObject(IN SAM_HANDLE ObjectHandle,
IN SECURITY_INFORMATION SecurityInformation,
OUT PSECURITY_DESCRIPTOR *SecurityDescriptor)
{
SAMPR_SR_SECURITY_DESCRIPTOR LocalSecurityDescriptor;
PSAMPR_SR_SECURITY_DESCRIPTOR pLocalSecurityDescriptor;
NTSTATUS Status;
TRACE("SamQuerySecurityObject(%p %lu %p)\n",
ObjectHandle, SecurityInformation, SecurityDescriptor);
LocalSecurityDescriptor.Length = 0;
LocalSecurityDescriptor.SecurityDescriptor = NULL;
RpcTryExcept
{
pLocalSecurityDescriptor = &LocalSecurityDescriptor;
Status = SamrQuerySecurityObject((SAMPR_HANDLE)ObjectHandle,
SecurityInformation,
&pLocalSecurityDescriptor);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
*SecurityDescriptor = LocalSecurityDescriptor.SecurityDescriptor;
return Status;
}
NTSTATUS
NTAPI
SamRemoveMemberFromAlias(IN SAM_HANDLE AliasHandle,
IN PSID MemberId)
{
NTSTATUS Status;
TRACE("SamRemoveMemberFromAlias(%p %ul)\n",
AliasHandle, MemberId);
RpcTryExcept
{
Status = SamrRemoveMemberFromAlias((SAMPR_HANDLE)AliasHandle,
MemberId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamRemoveMemberFromForeignDomain(IN SAM_HANDLE DomainHandle,
IN PSID MemberId)
{
NTSTATUS Status;
TRACE("SamRemoveMemberFromForeignDomain(%p %ul)\n",
DomainHandle, MemberId);
RpcTryExcept
{
Status = SamrRemoveMemberFromForeignDomain((SAMPR_HANDLE)DomainHandle,
MemberId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamRemoveMemberFromGroup(IN SAM_HANDLE GroupHandle,
IN ULONG MemberId)
{
NTSTATUS Status;
TRACE("SamRemoveMemberFromGroup(%p %ul)\n",
GroupHandle, MemberId);
RpcTryExcept
{
Status = SamrRemoveMemberFromGroup((SAMPR_HANDLE)GroupHandle,
MemberId);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamRemoveMultipleMembersFromAlias(IN SAM_HANDLE AliasHandle,
IN PSID *MemberIds,
IN ULONG MemberCount)
{
SAMPR_PSID_ARRAY Buffer;
NTSTATUS Status;
TRACE("SamRemoveMultipleMembersFromAlias(%p %p %lu)\n",
AliasHandle, MemberIds, MemberCount);
if (MemberIds == NULL)
return STATUS_INVALID_PARAMETER_2;
Buffer.Count = MemberCount;
Buffer.Sids = (PSAMPR_SID_INFORMATION)MemberIds;
RpcTryExcept
{
Status = SamrRemoveMultipleMembersFromAlias((SAMPR_HANDLE)AliasHandle,
&Buffer);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamRidToSid(IN SAM_HANDLE ObjectHandle,
IN ULONG Rid,
OUT PSID *Sid)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
SamSetInformationAlias(IN SAM_HANDLE AliasHandle,
@ -1165,6 +1557,88 @@ SamSetInformationUser(IN SAM_HANDLE UserHandle,
}
NTSTATUS
NTAPI
SamSetMemberAttributesOfGroup(IN SAM_HANDLE GroupHandle,
IN ULONG MemberId,
IN ULONG Attributes)
{
NTSTATUS Status;
TRACE("SamSetMemberAttributesOfGroup(%p %lu 0x%lx)\n",
GroupHandle, MemberId, Attributes);
RpcTryExcept
{
Status = SamrSetMemberAttributesOfGroup((SAMPR_HANDLE)GroupHandle,
MemberId,
Attributes);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
return Status;
}
NTSTATUS
NTAPI
SamSetSecurityObject(IN SAM_HANDLE ObjectHandle,
IN SECURITY_INFORMATION SecurityInformation,
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
{
SAMPR_SR_SECURITY_DESCRIPTOR DescriptorToPass;
ULONG Length;
NTSTATUS Status;
TRACE("SamSetSecurityObject(%p %lu %p)\n",
ObjectHandle, SecurityInformation, SecurityDescriptor);
/* Retrieve the length of the relative security descriptor */
Length = 0;
Status = RtlMakeSelfRelativeSD(SecurityDescriptor,
NULL,
&Length);
if (Status != STATUS_BUFFER_TOO_SMALL)
return STATUS_INVALID_PARAMETER;
/* Allocate a buffer for the security descriptor */
DescriptorToPass.Length = Length;
DescriptorToPass.SecurityDescriptor = MIDL_user_allocate(Length);
if (DescriptorToPass.SecurityDescriptor == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
/* Convert the given security descriptor to a relative security descriptor */
Status = RtlMakeSelfRelativeSD(SecurityDescriptor,
(PSECURITY_DESCRIPTOR)DescriptorToPass.SecurityDescriptor,
&Length);
if (!NT_SUCCESS(Status))
goto done;
RpcTryExcept
{
Status = SamrSetSecurityObject((SAMPR_HANDLE)ObjectHandle,
SecurityInformation,
&DescriptorToPass);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
Status = I_RpcMapWin32Status(RpcExceptionCode());
}
RpcEndExcept;
done:
if (DescriptorToPass.SecurityDescriptor != NULL)
MIDL_user_free(DescriptorToPass.SecurityDescriptor);
return Status;
}
NTSTATUS
NTAPI
SamShutdownSamServer(IN SAM_HANDLE ServerHandle)

View file

@ -1,6 +1,6 @@
@ stdcall SamAddMemberToAlias(ptr ptr)
@ stub SamAddMemberToGroup
@ stub SamAddMultipleMembersToAlias
@ stdcall SamAddMemberToGroup(ptr long long)
@ stdcall SamAddMultipleMembersToAlias(ptr ptr long)
@ stub SamChangePasswordUser2
@ stub SamChangePasswordUser3
@ stub SamChangePasswordUser
@ -11,9 +11,9 @@
@ stdcall SamCreateGroupInDomain(ptr ptr long ptr ptr)
@ stdcall SamCreateUser2InDomain(ptr ptr long long ptr ptr ptr)
@ stdcall SamCreateUserInDomain(ptr ptr long ptr ptr)
@ stub SamDeleteAlias
@ stub SamDeleteGroup
@ stub SamDeleteUser
@ stdcall SamDeleteAlias(ptr)
@ stdcall SamDeleteGroup(ptr)
@ stdcall SamDeleteUser(ptr)
@ stdcall SamEnumerateAliasesInDomain(ptr ptr ptr long ptr)
@ stdcall SamEnumerateDomainsInSamServer(ptr ptr ptr long ptr)
@ stdcall SamEnumerateGroupsInDomain(ptr ptr ptr long ptr)
@ -22,9 +22,9 @@
@ stdcall SamGetAliasMembership(ptr long ptr ptr ptr)
@ stub SamGetCompatibilityMode
@ stub SamGetDisplayEnumerationIndex
@ stub SamGetGroupsForUser
@ stdcall SamGetGroupsForUser(ptr ptr ptr)
@ stdcall SamGetMembersInAlias(ptr ptr ptr)
@ stub SamGetMembersInGroup
@ stdcall SamGetMembersInGroup(ptr ptr ptr ptr)
@ stdcall SamLookupDomainInSamServer(ptr ptr ptr)
@ stdcall SamLookupIdsInDomain(ptr long ptr ptr ptr)
@ stdcall SamLookupNamesInDomain(ptr long ptr ptr ptr)
@ -37,18 +37,18 @@
@ stdcall SamQueryInformationDomain(ptr long ptr)
@ stdcall SamQueryInformationGroup(ptr long ptr)
@ stdcall SamQueryInformationUser(ptr long ptr)
@ stub SamQuerySecurityObject
@ stub SamRemoveMemberFromAlias
@ stub SamRemoveMemberFromForeignDomain
@ stub SamRemoveMemberFromGroup
@ stub SamRemoveMultipleMembersFromAlias
@ stub SamRidToSid
@ stdcall SamQuerySecurityObject(ptr long ptr)
@ stdcall SamRemoveMemberFromAlias(ptr long)
@ stdcall SamRemoveMemberFromForeignDomain(ptr long)
@ stdcall SamRemoveMemberFromGroup(ptr long)
@ stdcall SamRemoveMultipleMembersFromAlias(ptr ptr long)
@ stdcall SamRidToSid(ptr long ptr)
@ stdcall SamSetInformationAlias(ptr long ptr)
@ stdcall SamSetInformationDomain(ptr long ptr)
@ stdcall SamSetInformationGroup(ptr long ptr)
@ stdcall SamSetInformationUser(ptr long ptr)
@ stub SamSetMemberAttributesOfGroup
@ stub SamSetSecurityObject
@ stdcall SamSetMemberAttributesOfGroup(ptr long long)
@ stdcall SamSetSecurityObject(ptr long ptr)
@ stdcall SamShutdownSamServer(ptr)
@ stub SamTestPrivateFunctionsDomain
@ stub SamTestPrivateFunctionsUser

View file

@ -83,26 +83,38 @@ static int SIC_LoadOverlayIcon(int icon_idx);
* NOTES
* Creates a new icon as a copy of the passed-in icon, overlayed with a
* shortcut image.
* FIXME: This should go to the ImageList implementation!
*/
static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
{ ICONINFO SourceIconInfo, ShortcutIconInfo, TargetIconInfo;
HICON ShortcutIcon, TargetIcon;
BITMAP SourceBitmapInfo, ShortcutBitmapInfo;
HDC SourceDC = NULL,
ShortcutDC = NULL,
TargetDC = NULL,
ScreenDC = NULL;
HBITMAP OldSourceBitmap = NULL,
OldShortcutBitmap = NULL,
{
ICONINFO ShortcutIconInfo, TargetIconInfo;
HICON ShortcutIcon = NULL, TargetIcon;
BITMAP TargetBitmapInfo, ShortcutBitmapInfo;
HDC ShortcutDC = NULL,
TargetDC = NULL;
HBITMAP OldShortcutBitmap = NULL,
OldTargetBitmap = NULL;
static int s_imgListIdx = -1;
ZeroMemory(&ShortcutIconInfo, sizeof(ShortcutIconInfo));
ZeroMemory(&TargetIconInfo, sizeof(TargetIconInfo));
/* Get information about the source icon and shortcut overlay */
if (! GetIconInfo(SourceIcon, &SourceIconInfo)
|| 0 == GetObjectW(SourceIconInfo.hbmColor, sizeof(BITMAP), &SourceBitmapInfo))
/* Get information about the source icon and shortcut overlay.
* We will write over the source bitmaps to get the final ones */
if (! GetIconInfo(SourceIcon, &TargetIconInfo))
return NULL;
/* Is it possible with the ImageList implementation? */
if(!TargetIconInfo.hbmColor)
{
return NULL;
/* Maybe we'll support this at some point */
FIXME("1bpp icon wants its overlay!\n");
goto fail;
}
if(!GetObjectW(TargetIconInfo.hbmColor, sizeof(BITMAP), &TargetBitmapInfo))
{
goto fail;
}
/* search for the shortcut icon only once */
@ -121,23 +133,25 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
} else
ShortcutIcon = NULL;
if (NULL == ShortcutIcon
|| ! GetIconInfo(ShortcutIcon, &ShortcutIconInfo)
|| 0 == GetObjectW(ShortcutIconInfo.hbmColor, sizeof(BITMAP), &ShortcutBitmapInfo))
if (!ShortcutIcon || !GetIconInfo(ShortcutIcon, &ShortcutIconInfo))
{
return NULL;
goto fail;
}
/* Is it possible with the ImageLists ? */
if(!ShortcutIconInfo.hbmColor)
{
/* Maybe we'll support this at some point */
FIXME("Should draw 1bpp overlay!\n");
goto fail;
}
if(!GetObjectW(ShortcutIconInfo.hbmColor, sizeof(BITMAP), &ShortcutBitmapInfo))
{
goto fail;
}
TargetIconInfo = SourceIconInfo;
TargetIconInfo.hbmMask = NULL;
TargetIconInfo.hbmColor = NULL;
/* Setup the source, shortcut and target masks */
SourceDC = CreateCompatibleDC(NULL);
if (NULL == SourceDC) goto fail;
OldSourceBitmap = (HBITMAP)SelectObject(SourceDC, SourceIconInfo.hbmMask);
if (NULL == OldSourceBitmap) goto fail;
/* Setup the masks */
ShortcutDC = CreateCompatibleDC(NULL);
if (NULL == ShortcutDC) goto fail;
OldShortcutBitmap = (HBITMAP)SelectObject(ShortcutDC, ShortcutIconInfo.hbmMask);
@ -145,44 +159,120 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
TargetDC = CreateCompatibleDC(NULL);
if (NULL == TargetDC) goto fail;
TargetIconInfo.hbmMask = CreateCompatibleBitmap(TargetDC, SourceBitmapInfo.bmWidth,
SourceBitmapInfo.bmHeight);
if (NULL == TargetIconInfo.hbmMask) goto fail;
ScreenDC = GetDC(NULL);
if (NULL == ScreenDC) goto fail;
TargetIconInfo.hbmColor = CreateCompatibleBitmap(ScreenDC, SourceBitmapInfo.bmWidth,
SourceBitmapInfo.bmHeight);
ReleaseDC(NULL, ScreenDC);
if (NULL == TargetIconInfo.hbmColor) goto fail;
OldTargetBitmap = (HBITMAP)SelectObject(TargetDC, TargetIconInfo.hbmMask);
if (NULL == OldTargetBitmap) goto fail;
/* Create the target mask by ANDing the source and shortcut masks */
if (! BitBlt(TargetDC, 0, 0, SourceBitmapInfo.bmWidth, SourceBitmapInfo.bmHeight,
SourceDC, 0, 0, SRCCOPY) ||
! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight,
ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
ShortcutDC, 0, 0, SRCAND))
/* Create the complete mask by ANDing the source and shortcut masks.
* NOTE: in an ImageList, all icons have the same dimensions */
if (!BitBlt(TargetDC, 0, 0, ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
ShortcutDC, 0, 0, SRCAND))
{
goto fail;
}
/* Setup the source and target xor bitmap */
if (NULL == SelectObject(SourceDC, SourceIconInfo.hbmColor) ||
/*
* We must remove or add the alpha component to the shortcut overlay:
* If we don't, SRCCOPY will copy it to our resulting icon, resulting in a
* partially transparent icons where it shouldn't be, and to an invisible icon
* if the underlying icon don't have any alpha channel information. (16bpp only icon for instance).
* But if the underlying icon has alpha channel information, then we must mark the overlay information
* as opaque.
* NOTE: This code sucks(tm) and should belong to the ImageList implementation.
* NOTE2: there are better ways to do this.
*/
if(ShortcutBitmapInfo.bmBitsPixel == 32)
{
BOOL add_alpha;
BYTE buffer[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
BITMAPINFO* lpbmi = (BITMAPINFO*)buffer;
PVOID bits;
PULONG pixel;
INT i, j;
/* Find if the source bitmap has an alpha channel */
if(TargetBitmapInfo.bmBitsPixel != 32) add_alpha = FALSE;
else
{
ZeroMemory(buffer, sizeof(buffer));
lpbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
lpbmi->bmiHeader.biWidth = TargetBitmapInfo.bmWidth;
lpbmi->bmiHeader.biHeight = TargetBitmapInfo.bmHeight;
lpbmi->bmiHeader.biPlanes = 1;
lpbmi->bmiHeader.biBitCount = 32;
bits = HeapAlloc(GetProcessHeap(), 0, TargetBitmapInfo.bmHeight * TargetBitmapInfo.bmWidthBytes);
if(!bits) goto fail;
if(!GetDIBits(TargetDC, TargetIconInfo.hbmColor, 0, TargetBitmapInfo.bmHeight, bits, lpbmi, DIB_RGB_COLORS))
{
ERR("GetBIBits failed!\n");
HeapFree(GetProcessHeap(), 0, bits);
goto fail;
}
i = j = 0;
pixel = (PULONG)bits;
for(i=0; i<TargetBitmapInfo.bmHeight; i++)
{
for(j=0; j<TargetBitmapInfo.bmWidth; j++)
{
add_alpha = (*pixel++ & 0xFF000000) != 0;
if(add_alpha) break;
}
if(add_alpha) break;
}
HeapFree(GetProcessHeap(), 0, bits);
}
/* Allocate the bits */
bits = HeapAlloc(GetProcessHeap(), 0, ShortcutBitmapInfo.bmHeight*ShortcutBitmapInfo.bmWidthBytes);
if(!bits) goto fail;
ZeroMemory(buffer, sizeof(buffer));
lpbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
lpbmi->bmiHeader.biWidth = ShortcutBitmapInfo.bmWidth;
lpbmi->bmiHeader.biHeight = ShortcutBitmapInfo.bmHeight;
lpbmi->bmiHeader.biPlanes = 1;
lpbmi->bmiHeader.biBitCount = 32;
if(!GetDIBits(TargetDC, ShortcutIconInfo.hbmColor, 0, ShortcutBitmapInfo.bmHeight, bits, lpbmi, DIB_RGB_COLORS))
{
ERR("GetBIBits failed!\n");
HeapFree(GetProcessHeap(), 0, bits);
goto fail;
}
pixel = (PULONG)bits;
/* Remove alpha channel component or make it totally opaque */
for(i=0; i<ShortcutBitmapInfo.bmHeight; i++)
{
for(j=0; j<ShortcutBitmapInfo.bmWidth; j++)
{
if(add_alpha) *pixel++ |= 0xFF000000;
else *pixel++ &= 0x00FFFFFF;
}
}
/* GetDIBits return BI_BITFIELDS with masks set to 0, and SetDIBits fails when masks are 0. The irony... */
lpbmi->bmiHeader.biCompression = BI_RGB;
/* Set the bits again */
if(!SetDIBits(TargetDC, ShortcutIconInfo.hbmColor, 0, ShortcutBitmapInfo.bmHeight, bits, lpbmi, DIB_RGB_COLORS))
{
ERR("SetBIBits failed!, %lu\n", GetLastError());
HeapFree(GetProcessHeap(), 0, bits);
goto fail;
}
HeapFree(GetProcessHeap(), 0, bits);
}
/* Now do the copy. We overwrite the original icon data */
if (NULL == SelectObject(ShortcutDC, ShortcutIconInfo.hbmColor) ||
NULL == SelectObject(TargetDC, TargetIconInfo.hbmColor))
{
goto fail;
}
/* Copy the source color bitmap to the target */
if (! BitBlt(TargetDC, 0, 0, SourceBitmapInfo.bmWidth, SourceBitmapInfo.bmHeight,
SourceDC, 0, 0, SRCCOPY)) goto fail;
/* Copy the source xor bitmap to the target and clear out part of it by using
the shortcut mask */
if (NULL == SelectObject(ShortcutDC, ShortcutIconInfo.hbmColor)) goto fail;
if (!MaskBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight,
ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
goto fail;
if (!MaskBlt(TargetDC, 0, 0, ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
ShortcutDC, 0, 0, ShortcutIconInfo.hbmMask, 0, 0,
MAKEROP4(0xAA0000, SRCCOPY)))
{
@ -192,11 +282,9 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
/* Clean up, we're not goto'ing to 'fail' after this so we can be lazy and not set
handles to NULL */
SelectObject(TargetDC, OldTargetBitmap);
DeleteObject(TargetDC);
DeleteDC(TargetDC);
SelectObject(ShortcutDC, OldShortcutBitmap);
DeleteObject(ShortcutDC);
SelectObject(SourceDC, OldSourceBitmap);
DeleteObject(SourceDC);
DeleteDC(ShortcutDC);
/* Create the icon using the bitmaps prepared earlier */
TargetIcon = CreateIconIndirect(&TargetIconInfo);
@ -204,19 +292,24 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
/* CreateIconIndirect copies the bitmaps, so we can release our bitmaps now */
DeleteObject(TargetIconInfo.hbmColor);
DeleteObject(TargetIconInfo.hbmMask);
/* Delete what GetIconInfo gave us */
DeleteObject(ShortcutIconInfo.hbmColor);
DeleteObject(ShortcutIconInfo.hbmMask);
DestroyIcon(ShortcutIcon);
return TargetIcon;
fail:
/* Clean up scratch resources we created */
if (NULL != OldTargetBitmap) SelectObject(TargetDC, OldTargetBitmap);
if (NULL != TargetDC) DeleteDC(TargetDC);
if (NULL != OldShortcutBitmap) SelectObject(ShortcutDC, OldShortcutBitmap);
if (NULL != ShortcutDC) DeleteDC(ShortcutDC);
if (NULL != TargetIconInfo.hbmColor) DeleteObject(TargetIconInfo.hbmColor);
if (NULL != TargetIconInfo.hbmMask) DeleteObject(TargetIconInfo.hbmMask);
if (NULL != TargetDC) DeleteObject(TargetDC);
if (NULL != OldShortcutBitmap) SelectObject(ShortcutDC, OldShortcutBitmap);
if (NULL != ShortcutDC) DeleteObject(ShortcutDC);
if (NULL != OldSourceBitmap) SelectObject(SourceDC, OldSourceBitmap);
if (NULL != SourceDC) DeleteObject(SourceDC);
if (NULL != ShortcutIconInfo.hbmColor) DeleteObject(ShortcutIconInfo.hbmColor);
if (NULL != ShortcutIconInfo.hbmMask) DeleteObject(ShortcutIconInfo.hbmColor);
if (NULL != ShortcutIcon) DestroyIcon(ShortcutIcon);
return NULL;
}
@ -228,7 +321,8 @@ fail:
* appends an icon pair to the end of the cache
*/
static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallIcon, HICON hBigIcon, DWORD dwFlags)
{ LPSIC_ENTRY lpsice;
{
LPSIC_ENTRY lpsice;
INT ret, index, index1;
WCHAR path[MAX_PATH];
TRACE("%s %i %p %p\n", debugstr_w(sSourceFile), dwSourceIndex, hSmallIcon ,hBigIcon);
@ -247,23 +341,38 @@ static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallI
index = DPA_InsertPtr(sic_hdpa, 0x7fff, lpsice);
if ( INVALID_INDEX == index )
{
HeapFree(GetProcessHeap(), 0, lpsice->sSourceFile);
SHFree(lpsice);
ret = INVALID_INDEX;
ret = INVALID_INDEX;
goto leave;
}
else
index = ImageList_AddIcon (ShellSmallIconList, hSmallIcon);
index1= ImageList_AddIcon (ShellBigIconList, hBigIcon);
/* Something went wrong when allocating a new image in the list. Abort. */
if((index == -1) || (index1 == -1))
{
index = ImageList_AddIcon (ShellSmallIconList, hSmallIcon);
index1= ImageList_AddIcon (ShellBigIconList, hBigIcon);
if (index!=index1)
{
FIXME("iconlists out of sync 0x%x 0x%x\n", index, index1);
}
lpsice->dwListIndex = index;
ret = lpsice->dwListIndex;
WARN("Something went wrong when adding the icon to the list: small - 0x%x, big - 0x%x.\n",
index, index1);
if(index != -1) ImageList_Remove(ShellSmallIconList, index);
if(index1 != -1) ImageList_Remove(ShellBigIconList, index1);
ret = INVALID_INDEX;
goto leave;
}
if (index!=index1)
{
FIXME("iconlists out of sync 0x%x 0x%x\n", index, index1);
/* What to do ???? */
}
lpsice->dwListIndex = index;
ret = lpsice->dwListIndex;
leave:
if(ret == INVALID_INDEX)
{
HeapFree(GetProcessHeap(), 0, lpsice->sSourceFile);
SHFree(lpsice);
}
LeaveCriticalSection(&SHELL32_SicCS);
return ret;
}
@ -274,23 +383,23 @@ static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallI
* gets small/big icon by number from a file
*/
static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags)
{ HICON hiconLarge=0;
HICON hiconSmall=0;
HICON hiconLargeShortcut;
HICON hiconSmallShortcut;
#if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER)
{
HICON hiconLarge=0;
HICON hiconSmall=0;
UINT ret;
static UINT (WINAPI*PrivateExtractIconExW)(LPCWSTR,int,HICON*,HICON*,UINT) = NULL;
if (!PrivateExtractIconExW) {
if (!PrivateExtractIconExW)
{
HMODULE hUser32 = GetModuleHandleA("user32");
PrivateExtractIconExW = (UINT(WINAPI*)(LPCWSTR,int,HICON*,HICON*,UINT)) GetProcAddress(hUser32, "PrivateExtractIconExW");
}
if (PrivateExtractIconExW)
if (PrivateExtractIconExW)
{
PrivateExtractIconExW(sSourceFile, dwSourceIndex, &hiconLarge, &hiconSmall, 1);
}
else
#endif
{
PrivateExtractIconsW(sSourceFile, dwSourceIndex, 32, 32, &hiconLarge, NULL, 1, 0);
PrivateExtractIconsW(sSourceFile, dwSourceIndex, 16, 16, &hiconSmall, NULL, 1, 0);
@ -298,29 +407,36 @@ static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags)
if ( !hiconLarge || !hiconSmall)
{
WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex, debugstr_w(sSourceFile), hiconLarge, hiconSmall);
return -1;
WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex, debugstr_w(sSourceFile), hiconLarge, hiconSmall);
if(hiconLarge) DestroyIcon(hiconLarge);
if(hiconSmall) DestroyIcon(hiconSmall);
return INVALID_INDEX;
}
if (0 != (dwFlags & GIL_FORSHORTCUT))
{
hiconLargeShortcut = SIC_OverlayShortcutImage(hiconLarge, TRUE);
hiconSmallShortcut = SIC_OverlayShortcutImage(hiconSmall, FALSE);
if (NULL != hiconLargeShortcut && NULL != hiconSmallShortcut)
{
hiconLarge = hiconLargeShortcut;
hiconSmall = hiconSmallShortcut;
}
else
{
WARN("Failed to create shortcut overlayed icons\n");
if (NULL != hiconLargeShortcut) DestroyIcon(hiconLargeShortcut);
if (NULL != hiconSmallShortcut) DestroyIcon(hiconSmallShortcut);
dwFlags &= ~ GIL_FORSHORTCUT;
}
HICON hiconLargeShortcut = SIC_OverlayShortcutImage(hiconLarge, TRUE);
HICON hiconSmallShortcut = SIC_OverlayShortcutImage(hiconSmall, FALSE);
if (NULL != hiconLargeShortcut && NULL != hiconSmallShortcut)
{
DestroyIcon(hiconLarge);
DestroyIcon(hiconSmall);
hiconLarge = hiconLargeShortcut;
hiconSmall = hiconSmallShortcut;
}
else
{
WARN("Failed to create shortcut overlayed icons\n");
if (NULL != hiconLargeShortcut) DestroyIcon(hiconLargeShortcut);
if (NULL != hiconSmallShortcut) DestroyIcon(hiconSmallShortcut);
dwFlags &= ~ GIL_FORSHORTCUT;
}
}
return SIC_IconAppend (sSourceFile, dwSourceIndex, hiconSmall, hiconLarge, dwFlags);
ret = SIC_IconAppend (sSourceFile, dwSourceIndex, hiconSmall, hiconLarge, dwFlags);
DestroyIcon(hiconLarge);
DestroyIcon(hiconSmall);
return ret;
}
/*****************************************************************************
* SIC_GetIconIndex [internal]
@ -367,6 +483,7 @@ INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags )
LeaveCriticalSection(&SHELL32_SicCS);
return ret;
}
/*****************************************************************************
* SIC_Initialize [internal]
*/
@ -378,6 +495,7 @@ BOOL SIC_Initialize(void)
HDC hDC;
INT bpp;
DWORD ilMask;
BOOL result = FALSE;
TRACE("Entered SIC_Initialize\n");
@ -397,11 +515,11 @@ BOOL SIC_Initialize(void)
if (!hDC)
{
ERR("Failed to create information context (error %d)\n", GetLastError());
return FALSE;
goto end;
}
bpp = GetDeviceCaps(hDC, BITSPIXEL);
ReleaseDC(NULL, hDC);
DeleteDC(hDC);
if (bpp <= 4)
ilMask = ILC_COLOR4;
@ -428,61 +546,83 @@ BOOL SIC_Initialize(void)
ilMask,
100,
100);
if (!ShellSmallIconList)
{
ERR("Failed to create the small icon list.\n");
goto end;
}
ShellBigIconList = ImageList_Create(cx_large,
cy_large,
ilMask,
100,
100);
if (ShellSmallIconList)
if (!ShellBigIconList)
{
/* Load the document icon, which is used as the default if an icon isn't found. */
hSm = (HICON)LoadImageW(shell32_hInstance,
MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT),
IMAGE_ICON,
cx_small,
cy_small,
LR_SHARED | LR_DEFAULTCOLOR);
if (!hSm)
{
ERR("Failed to load IDI_SHELL_DOCUMENT icon1!\n");
return FALSE;
}
ERR("Failed to create the big icon list.\n");
goto end;
}
else
/* Load the document icon, which is used as the default if an icon isn't found. */
hSm = (HICON)LoadImageW(shell32_hInstance,
MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT),
IMAGE_ICON,
cx_small,
cy_small,
LR_SHARED | LR_DEFAULTCOLOR);
if (!hSm)
{
ERR("Failed to load ShellSmallIconList\n");
return FALSE;
ERR("Failed to load small IDI_SHELL_DOCUMENT icon!\n");
goto end;
}
if (ShellBigIconList)
hLg = (HICON)LoadImageW(shell32_hInstance,
MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT),
IMAGE_ICON,
cx_large,
cy_large,
LR_SHARED | LR_DEFAULTCOLOR);
if (!hLg)
{
hLg = (HICON)LoadImageW(shell32_hInstance,
MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT),
IMAGE_ICON,
cx_large,
cy_large,
LR_SHARED | LR_DEFAULTCOLOR);
if (!hLg)
{
ERR("Failed to load IDI_SHELL_DOCUMENT icon2!\n");
DestroyIcon(hSm);
return FALSE;
}
}
else
{
ERR("Failed to load ShellBigIconList\n");
return FALSE;
ERR("Failed to load large IDI_SHELL_DOCUMENT icon!\n");
goto end;
}
SIC_IconAppend(swShell32Name, IDI_SHELL_DOCUMENT-1, hSm, hLg, 0);
SIC_IconAppend(swShell32Name, -IDI_SHELL_DOCUMENT, hSm, hLg, 0);
if(SIC_IconAppend(swShell32Name, IDI_SHELL_DOCUMENT-1, hSm, hLg, 0) == INVALID_INDEX)
{
ERR("Failed to add IDI_SHELL_DOCUMENT icon to cache.\n");
goto end;
}
if(SIC_IconAppend(swShell32Name, -IDI_SHELL_DOCUMENT, hSm, hLg, 0) == INVALID_INDEX)
{
ERR("Failed to add IDI_SHELL_DOCUMENT icon to cache.\n");
goto end;
}
/* Everything went fine */
result = TRUE;
end:
/* The image list keeps a copy of the icons, we must destroy them */
if(hSm) DestroyIcon(hSm);
if(hLg) DestroyIcon(hLg);
/* Clean everything if something went wrong */
if(!result)
{
if(sic_hdpa) DPA_Destroy(sic_hdpa);
if(ShellSmallIconList) ImageList_Destroy(ShellSmallIconList);
if(ShellBigIconList) ImageList_Destroy(ShellSmallIconList);
sic_hdpa = NULL;
ShellSmallIconList = NULL;
ShellBigIconList = NULL;
}
TRACE("hIconSmall=%p hIconBig=%p\n",ShellSmallIconList, ShellBigIconList);
return TRUE;
return result;
}
/*************************************************************************
* SIC_Destroy
*

View file

@ -306,6 +306,38 @@ HidP_GetScaledUsageValue(
return HidParser_GetScaledUsageValue(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetUsageValue(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection,
IN USAGE Usage,
OUT PULONG UsageValue,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN PCHAR Report,
IN ULONG ReportLength)
{
HID_PARSER Parser;
//
// sanity check
//
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
//
// init parser
//
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
//
// get scaled usage value
//
return HidParser_GetUsageValue(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
}
HIDAPI
NTSTATUS
NTAPI
@ -405,24 +437,6 @@ HidP_GetLinkCollectionNodes(
return STATUS_NOT_IMPLEMENTED;
}
HIDAPI
NTSTATUS
NTAPI
HidP_GetUsageValue(
IN HIDP_REPORT_TYPE ReportType,
IN USAGE UsagePage,
IN USHORT LinkCollection,
IN USAGE Usage,
OUT PULONG UsageValue,
IN PHIDP_PREPARSED_DATA PreparsedData,
IN PCHAR Report,
IN ULONG ReportLength)
{
UNIMPLEMENTED
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
HidP_SysPowerEvent (

View file

@ -37,6 +37,7 @@ MouHid_GetButtonMove(
OUT PLONG LastY)
{
NTSTATUS Status;
ULONG ValueX, ValueY;
/* init result */
*LastX = 0;
@ -44,17 +45,50 @@ MouHid_GetButtonMove(
/* get scaled usage value x */
Status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, (PLONG)LastX, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
/* FIXME handle error */
ASSERT(Status == HIDP_STATUS_SUCCESS);
if (Status != HIDP_STATUS_SUCCESS)
{
/* FIXME: handle more errors */
if (Status == HIDP_STATUS_BAD_LOG_PHY_VALUES)
{
/* FIXME: assume it operates in absolute mode */
DeviceExtension->MouseAbsolute = TRUE;
/* get unscaled value */
Status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, (PULONG)&ValueX, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
/* FIXME handle error */
ASSERT(Status == HIDP_STATUS_SUCCESS);
/* absolute pointing devices values need be in range 0 - 0xffff */
ASSERT(DeviceExtension->ValueCapsX.LogicalMax > 0);
*LastX = (ValueX * 0xFFFF) / DeviceExtension->ValueCapsX.LogicalMax;
}
}
/* get scaled usage value y */
Status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, (PLONG)LastY, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
/* FIXME handle error */
ASSERT(Status == HIDP_STATUS_SUCCESS);
if (Status != HIDP_STATUS_SUCCESS)
{
// FIXME: handle more errors
if (Status == HIDP_STATUS_BAD_LOG_PHY_VALUES)
{
// assume it operates in absolute mode
DeviceExtension->MouseAbsolute = TRUE;
// get unscaled value
Status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, (PULONG)&ValueY, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
/* FIXME handle error */
ASSERT(Status == HIDP_STATUS_SUCCESS);
/* absolute pointing devices values need be in range 0 - 0xffff */
ASSERT(DeviceExtension->ValueCapsY.LogicalMax);
*LastY = (ValueY * 0xFFFF) / DeviceExtension->ValueCapsY.LogicalMax;
}
}
}
VOID
MouHid_GetButtonFlags(
IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
@ -132,6 +166,12 @@ MouHid_GetButtonFlags(
TempList = DeviceExtension->CurrentUsageList;
DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList;
DeviceExtension->PreviousUsageList = TempList;
if (DeviceExtension->MouseAbsolute)
{
// mouse operates absolute
*ButtonFlags |= MOUSE_MOVE_ABSOLUTE;
}
}
VOID
@ -195,12 +235,12 @@ MouHid_ReadCompletion(
return STATUS_MORE_PROCESSING_REQUIRED;
}
/* get mouse change flags */
MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags);
/* get mouse change */
MouHid_GetButtonMove(DeviceExtension, &LastX, &LastY);
/* get mouse change flags */
MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags);
/* init input data */
RtlZeroMemory(&MouseInputData, sizeof(MOUSE_INPUT_DATA));
@ -227,6 +267,12 @@ MouHid_ReadCompletion(
}
}
DPRINT("[MOUHID] ReportData %02x %02x %02x %02x %02x %02x %02x\n",
DeviceExtension->Report[0] & 0xFF,
DeviceExtension->Report[1] & 0xFF, DeviceExtension->Report[2] & 0xFF,
DeviceExtension->Report[3] & 0xFF, DeviceExtension->Report[4] & 0xFF,
DeviceExtension->Report[5] & 0xFF, DeviceExtension->Report[6] & 0xFF);
DPRINT("[MOUHID] LastX %ld LastY %ld Flags %x ButtonData %x\n", MouseInputData.LastX, MouseInputData.LastY, MouseInputData.ButtonFlags, MouseInputData.ButtonData);
/* dispatch mouse action */
@ -700,10 +746,10 @@ MouHid_StartDevice(
DeviceExtension->PreparsedData = PreparsedData;
ValueCapsLength = 1;
HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, &ValueCaps, &ValueCapsLength, PreparsedData);
HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, &DeviceExtension->ValueCapsX, &ValueCapsLength, PreparsedData);
ValueCapsLength = 1;
HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, &ValueCaps, &ValueCapsLength, PreparsedData);
HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, &DeviceExtension->ValueCapsY, &ValueCapsLength, PreparsedData);
/* now check for wheel mouse support */
ValueCapsLength = 1;

View file

@ -109,6 +109,22 @@ typedef struct
//
UCHAR StopReadReport;
//
// mouse absolute
//
UCHAR MouseAbsolute;
//
// value caps x
//
HIDP_VALUE_CAPS ValueCapsX;
//
// value caps y button
//
HIDP_VALUE_CAPS ValueCapsY;
}MOUHID_DEVICE_EXTENSION, *PMOUHID_DEVICE_EXTENSION;
#define WHEEL_DELTA 120

View file

@ -474,8 +474,11 @@ USBD_ParseDescriptors(
return CommonDescriptor;
}
/* sanity check */
ASSERT(CommonDescriptor->bLength);
if (CommonDescriptor->bLength == 0)
{
/* invalid usb descriptor */
return NULL;
}
/* move to next descriptor */
CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);

View file

@ -819,6 +819,7 @@ CreateDeviceIds(
LPWSTR DeviceString;
WCHAR Buffer[200];
PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
PHUB_DEVICE_EXTENSION HubDeviceExtension;
PUSB_DEVICE_DESCRIPTOR DeviceDescriptor;
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
@ -828,6 +829,9 @@ CreateDeviceIds(
//
UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension;
// get hub device extension
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbChildExtension->ParentDeviceObject->DeviceExtension;
//
// get device descriptor
//
@ -1011,10 +1015,12 @@ CreateDeviceIds(
//
if (UsbChildExtension->DeviceDesc.iSerialNumber)
{
LPWSTR SerialBuffer = NULL;
Status = GetUsbStringDescriptor(UsbChildDeviceObject,
UsbChildExtension->DeviceDesc.iSerialNumber,
0,
(PVOID*)&UsbChildExtension->usInstanceId.Buffer,
(PVOID*)&SerialBuffer,
&UsbChildExtension->usInstanceId.Length);
if (!NT_SUCCESS(Status))
{
@ -1022,15 +1028,31 @@ CreateDeviceIds(
return Status;
}
UsbChildExtension->usInstanceId.MaximumLength = UsbChildExtension->usInstanceId.Length;
DPRINT("Usb InstanceId %wZ\n", &UsbChildExtension->usInstanceId);
// construct instance id buffer
Index = swprintf(Buffer, L"%04d&%s", HubDeviceExtension->InstanceCount, SerialBuffer) + 1;
UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
if (UsbChildExtension->usInstanceId.Buffer == NULL)
{
DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR));
Status = STATUS_INSUFFICIENT_RESOURCES;
return Status;
}
//
// copy instance id
//
RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR));
UsbChildExtension->usInstanceId.Length = UsbChildExtension->usInstanceId.MaximumLength = Index * sizeof(WCHAR);
ExFreePool(SerialBuffer);
DPRINT("Usb InstanceId %wZ InstanceCount %x\n", &UsbChildExtension->usInstanceId, HubDeviceExtension->InstanceCount);
}
else
{
//
// the device did not provide a serial number, lets create a pseudo instance id
//
Index = swprintf(Buffer, L"0&%04d", UsbChildExtension->PortNumber) + 1;
Index = swprintf(Buffer, L"%04d&%04d", HubDeviceExtension->InstanceCount, UsbChildExtension->PortNumber) + 1;
UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
if (UsbChildExtension->usInstanceId.Buffer == NULL)
{
@ -1304,6 +1326,7 @@ CreateUsbChildDeviceObject(
}
HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] = NewChildDeviceObject;
HubDeviceExtension->InstanceCount++;
IoInvalidateDeviceRelations(RootHubDeviceObject, BusRelations);
return STATUS_SUCCESS;

View file

@ -558,6 +558,7 @@ USBHUB_PdoHandlePnp(
ULONG Index;
ULONG bFound;
PDEVICE_RELATIONS DeviceRelation;
PDEVICE_OBJECT ParentDevice;
UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
@ -645,6 +646,7 @@ USBHUB_PdoHandlePnp(
{
PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension;
PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface;
ParentDevice = UsbChildExtension->ParentDeviceObject;
DPRINT("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
@ -671,10 +673,13 @@ USBHUB_PdoHandlePnp(
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
/* delete device */
IoDeleteDevice(DeviceObject);
if (bFound)
{
/* Delete the device object */
IoDeleteDevice(DeviceObject);
/* invalidate device relations */
IoInvalidateDeviceRelations(ParentDevice, BusRelations);
}
return STATUS_SUCCESS;
@ -731,6 +736,12 @@ USBHUB_PdoHandlePnp(
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(UsbChildExtension->ParentDeviceObject, Irp);
}
case IRP_MN_SURPRISE_REMOVAL:
{
DPRINT("[USBHUB] HandlePnp IRP_MN_SURPRISE_REMOVAL\n");
Status = STATUS_SUCCESS;
break;
}
default:
{
DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);

View file

@ -103,8 +103,9 @@ typedef struct _HUB_DEVICE_EXTENSION
PVOID RootHubHandle;
USB_BUS_INTERFACE_USBDI_V2 DeviceInterface;
UNICODE_STRING SymbolicLinkName;
ULONG InstanceCount;
} HUB_DEVICE_EXTENSION, *PHUB_DEVICE_EXTENSION;
// createclose.c

View file

@ -125,10 +125,19 @@ USBSTOR_FdoHandleRemoveDevice(
IN OUT PIRP Irp)
{
NTSTATUS Status;
ULONG Index;
DPRINT("Handling FDO removal\n");
DPRINT("Handling FDO removal %p\n", DeviceObject);
/* We don't need to request removal of our children here */
/* FIXME: wait for devices finished processing */
for(Index = 0; Index < 16; Index++)
{
if (DeviceExtension->ChildPDO[Index] != NULL)
{
DPRINT("Deleting PDO %p RefCount %x AttachedDevice %p \n", DeviceExtension->ChildPDO[Index], DeviceExtension->ChildPDO[Index]->ReferenceCount, DeviceExtension->ChildPDO[Index]->AttachedDevice);
IoDeleteDevice(DeviceExtension->ChildPDO[Index]);
}
}
/* Send the IRP down the stack */
IoSkipCurrentIrpStackLocation(Irp);
@ -264,7 +273,7 @@ USBSTOR_FdoHandleStartDevice(
//
// create pdo
//
Status = USBSTOR_CreatePDO(DeviceObject, Index, &DeviceExtension->ChildPDO[Index]);
Status = USBSTOR_CreatePDO(DeviceObject, Index);
//
// check for failure
@ -282,6 +291,7 @@ USBSTOR_FdoHandleStartDevice(
// increment pdo index
//
Index++;
DeviceExtension->InstanceCount++;
}while(Index < DeviceExtension->MaxLUN);
@ -340,8 +350,20 @@ USBSTOR_FdoHandlePnp(
switch(IoStack->MinorFunction)
{
case IRP_MN_SURPRISE_REMOVAL:
{
DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// forward irp to next device object
//
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
}
case IRP_MN_QUERY_DEVICE_RELATIONS:
{
DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject);
Status = USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp);
break;
}

View file

@ -676,9 +676,9 @@ USBSTOR_PdoHandleQueryInstanceId(
else
{
//
// FIXME: should use some random value
// use instance count and LUN
//
swprintf(Buffer, L"%s&%d", L"00000000", PDODeviceExtension->LUN);
swprintf(Buffer, L"%04d&%d", FDODeviceExtension->InstanceCount, PDODeviceExtension->LUN);
}
//
@ -897,7 +897,7 @@ USBSTOR_PdoHandlePnp(
// check if no unique id
//
Caps = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
Caps->UniqueID = TRUE; //FIXME
Caps->UniqueID = FALSE; // no unique id is supported
Caps->Removable = TRUE; //FIXME
}
break;
@ -929,6 +929,11 @@ USBSTOR_PdoHandlePnp(
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_SURPRISE_REMOVAL:
{
Status = STATUS_SUCCESS;
break;
}
default:
{
//
@ -1256,13 +1261,19 @@ USBSTOR_SendFormatCapacityIrp(
NTSTATUS
USBSTOR_CreatePDO(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR LUN,
OUT PDEVICE_OBJECT *ChildDeviceObject)
IN UCHAR LUN)
{
PDEVICE_OBJECT PDO;
NTSTATUS Status;
PPDO_DEVICE_EXTENSION PDODeviceExtension;
PUFI_INQUIRY_RESPONSE Response;
PFDO_DEVICE_EXTENSION FDODeviceExtension;
//
// get device extension
//
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
//
// create child device object
@ -1292,7 +1303,7 @@ USBSTOR_CreatePDO(
RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
PDODeviceExtension->Common.IsFDO = FALSE;
PDODeviceExtension->LowerDeviceObject = DeviceObject;
PDODeviceExtension->PDODeviceObject = ChildDeviceObject;
PDODeviceExtension->PDODeviceObject = &FDODeviceExtension->ChildPDO[LUN];
PDODeviceExtension->Self = PDO;
PDODeviceExtension->LUN = LUN;
@ -1309,7 +1320,7 @@ USBSTOR_CreatePDO(
//
// output device object
//
*ChildDeviceObject = PDO;
FDODeviceExtension->ChildPDO[LUN] = PDO;
//
// send inquiry command by irp

View file

@ -71,6 +71,7 @@ typedef struct
PSCSI_REQUEST_BLOCK LastTimerActiveSrb; // last timer tick active srb
ULONG SrbErrorHandlingActive; // error handling of srb is activated
ULONG TimerWorkQueueEnabled; // timer work queue enabled
ULONG InstanceCount; // pdo instance count
}FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
typedef struct
@ -364,8 +365,7 @@ USBSTOR_PdoHandlePnp(
NTSTATUS
USBSTOR_CreatePDO(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR LUN,
OUT PDEVICE_OBJECT *ChildDeviceObject);
IN UCHAR LUN);
//---------------------------------------------------------------------
//

View file

@ -271,6 +271,12 @@ typedef enum _GROUP_INFORMATION_CLASS
GroupReplicationInformation
} GROUP_INFORMATION_CLASS;
typedef struct _GROUP_MEMBERSHIP
{
ULONG RelativeId;
ULONG Attributes;
} GROUP_MEMBERSHIP, *PGROUP_MEMBERSHIP;
typedef enum _USER_INFORMATION_CLASS
{
UserGeneralInformation = 1,
@ -322,6 +328,12 @@ SamAddMemberToGroup(IN SAM_HANDLE GroupHandle,
IN ULONG MemberId,
IN ULONG Attributes);
NTSTATUS
NTAPI
SamAddMultipleMembersToAlias(IN SAM_HANDLE AliasHandle,
IN PSID *MemberIds,
IN ULONG MemberCount);
NTSTATUS
NTAPI
SamCloseHandle(IN SAM_HANDLE SamHandle);
@ -367,6 +379,18 @@ SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
OUT PSAM_HANDLE UserHandle,
OUT PULONG RelativeId);
NTSTATUS
NTAPI
SamDeleteAlias(IN SAM_HANDLE AliasHandle);
NTSTATUS
NTAPI
SamDeleteGroup(IN SAM_HANDLE GroupHandle);
NTSTATUS
NTAPI
SamDeleteUser(IN SAM_HANDLE UserHandle);
NTSTATUS
NTAPI
SamEnumerateAliasesInDomain(IN SAM_HANDLE DomainHandle,
@ -412,12 +436,25 @@ SamGetAliasMembership(IN SAM_HANDLE DomainHandle,
OUT PULONG MembershipCount,
OUT PULONG *Aliases);
NTSTATUS
NTAPI
SamGetGroupsForUser(IN SAM_HANDLE UserHandle,
OUT PGROUP_MEMBERSHIP *Groups,
OUT PULONG MembershipCount);
NTSTATUS
NTAPI
SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
OUT PSID **MemberIds,
OUT PULONG MemberCount);
NTSTATUS
NTAPI
SamGetMembersInGroup(IN SAM_HANDLE GroupHandle,
OUT PULONG *MemberIds,
OUT PULONG *Attributes,
OUT PULONG MemberCount);
NTSTATUS
NTAPI
SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
@ -492,11 +529,39 @@ SamQueryInformationUser(IN SAM_HANDLE UserHandle,
IN USER_INFORMATION_CLASS UserInformationClass,
OUT PVOID *Buffer);
NTSTATUS
NTAPI
SamQuerySecurityObject(IN SAM_HANDLE ObjectHandle,
IN SECURITY_INFORMATION SecurityInformation,
OUT PSECURITY_DESCRIPTOR *SecurityDescriptor);
NTSTATUS
NTAPI
SamRemoveMemberFromAlias(IN SAM_HANDLE AliasHandle,
IN PSID MemberId);
NTSTATUS
NTAPI
SamRemoveMemberFromForeignDomain(IN SAM_HANDLE DomainHandle,
IN PSID MemberId);
NTSTATUS
NTAPI
SamRemoveMemberFromGroup(IN SAM_HANDLE GroupHandle,
IN ULONG MemberId);
NTSTATUS
NTAPI
SamRemoveMultipleMembersFromAlias(IN SAM_HANDLE AliasHandle,
IN PSID *MemberIds,
IN ULONG MemberCount);
NTSTATUS
NTAPI
SamRidToSid(IN SAM_HANDLE ObjectHandle,
IN ULONG Rid,
OUT PSID *Sid);
NTSTATUS
NTAPI
SamSetInformationAlias(IN SAM_HANDLE AliasHandle,
@ -521,6 +586,18 @@ SamSetInformationUser(IN SAM_HANDLE UserHandle,
IN USER_INFORMATION_CLASS UserInformationClass,
IN PVOID Buffer);
NTSTATUS
NTAPI
SamSetMemberAttributesOfGroup(IN SAM_HANDLE GroupHandle,
IN ULONG MemberId,
IN ULONG Attributes);
NTSTATUS
NTAPI
SamSetSecurityObject(IN SAM_HANDLE ObjectHandle,
IN SECURITY_INFORMATION SecurityInformation,
IN PSECURITY_DESCRIPTOR SecurityDescriptor);
NTSTATUS
NTAPI
SamShutdownSamServer(IN SAM_HANDLE ServerHandle);

View file

@ -99,11 +99,13 @@ typedef struct _SAMPR_SR_SECURITY_DESCRIPTOR
[size_is(Length)] unsigned char* SecurityDescriptor;
} SAMPR_SR_SECURITY_DESCRIPTOR, *PSAMPR_SR_SECURITY_DESCRIPTOR;
cpp_quote("#ifndef _NTSAM_")
typedef struct _GROUP_MEMBERSHIP
{
unsigned long RelativeId;
unsigned long Attributes;
} GROUP_MEMBERSHIP, *PGROUP_MEMBERSHIP;
cpp_quote("#endif")
typedef struct _SAMPR_GET_GROUPS_BUFFER
{

View file

@ -24,23 +24,23 @@
#define WINE_UNICODE_INLINE static inline
#endif
#define memicmpW(s1,s2,n) _wcsnicmp((const wchar_t *)(s1),(const wchar_t *)(s2),(n))
#define strlenW(s) wcslen((const wchar_t *)(s))
#define strcpyW(d,s) wcscpy((wchar_t *)(d),(const wchar_t *)(s))
#define strcatW(d,s) wcscat((wchar_t *)(d),(const wchar_t *)(s))
#define strcspnW(d,s) wcscspn((wchar_t *)(d),(const wchar_t *)(s))
#define strstrW(d,s) wcsstr((const wchar_t *)(d),(const wchar_t *)(s))
#define strtolW(s,e,b) wcstol((const wchar_t *)(s),(wchar_t **)(e),(b))
#define strchrW(s,c) wcschr((const wchar_t *)(s),(wchar_t)(c))
#define strrchrW(s,c) wcsrchr((const wchar_t *)(s),(wchar_t)(c))
#define strncmpW(s1,s2,n) wcsncmp((const wchar_t *)(s1),(const wchar_t *)(s2),(n))
#define strncpyW(s1,s2,n) wcsncpy((wchar_t *)(s1),(const wchar_t *)(s2),(n))
#define strcmpW(s1,s2) wcscmp((const wchar_t *)(s1),(const wchar_t *)(s2))
#define strcmpiW(s1,s2) _wcsicmp((const wchar_t *)(s1),(const wchar_t *)(s2))
#define strncmpiW(s1,s2,n) _wcsnicmp((const wchar_t *)(s1),(const wchar_t *)(s2),(n))
#define strtoulW(s1,s2,b) wcstoul((const wchar_t *)(s1),(wchar_t **)(s2),(b))
#define strspnW(str, accept) wcsspn((const wchar_t *)(str), (const wchar_t *)(accept))
#define strpbrkW(str, accept) wcspbrk((const wchar_t *)(str), (const wchar_t *)(accept))
#define memicmpW(s1,s2,n) _wcsnicmp((s1),(s2),(n))
#define strlenW(s) wcslen((s))
#define strcpyW(d,s) wcscpy((d),(s))
#define strcatW(d,s) wcscat((d),(s))
#define strcspnW(d,s) wcscspn((d),(s))
#define strstrW(d,s) wcsstr((d),(s))
#define strtolW(s,e,b) wcstol((s),(e),(b))
#define strchrW(s,c) wcschr((s),(c))
#define strrchrW(s,c) wcsrchr((s),(c))
#define strncmpW(s1,s2,n) wcsncmp((s1),(s2),(n))
#define strncpyW(s1,s2,n) wcsncpy((s1),(s2),(n))
#define strcmpW(s1,s2) wcscmp((s1),(s2))
#define strcmpiW(s1,s2) _wcsicmp((s1),(s2))
#define strncmpiW(s1,s2,n) _wcsnicmp((s1),(s2),(n))
#define strtoulW(s1,s2,b) wcstoul((s1),(s2),(b))
#define strspnW(str, accept) wcsspn((str),(accept))
#define strpbrkW(str, accept) wcspbrk((str),(accept))
#define tolowerW(n) towlower((n))
#define toupperW(n) towupper((n))
#define islowerW(n) iswlower((n))
@ -51,10 +51,10 @@
#define isxdigitW(n) iswxdigit((n))
#define isspaceW(n) iswspace((n))
#define iscntrlW(n) iswcntrl((n))
#define atoiW(s) _wtoi((const wchar_t *)(s))
#define atolW(s) _wtol((const wchar_t *)(s))
#define strlwrW(s) _wcslwr((wchar_t *)(s))
#define struprW(s) _wcsupr((wchar_t *)(s))
#define atoiW(s) _wtoi((s))
#define atolW(s) _wtol((s))
#define strlwrW(s) _wcslwr((s))
#define struprW(s) _wcsupr((s))
#define sprintfW swprintf
#define vsprintfW vswprintf
#define snprintfW _snwprintf

View file

@ -563,6 +563,103 @@ HidParser_UsesReportId(
}
HIDPARSER_STATUS
HidParser_GetUsageValueWithReport(
IN PHID_PARSER Parser,
IN PVOID CollectionContext,
IN UCHAR ReportType,
IN USAGE UsagePage,
IN USAGE Usage,
OUT PULONG UsageValue,
IN PCHAR ReportDescriptor,
IN ULONG ReportDescriptorLength)
{
ULONG Index;
PHID_REPORT Report;
USHORT CurrentUsagePage;
PHID_REPORT_ITEM ReportItem;
ULONG Data;
//
// get report
//
Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
if (!Report)
{
//
// no such report
//
return HIDPARSER_STATUS_REPORT_NOT_FOUND;
}
if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
{
//
// invalid report descriptor length
//
return HIDPARSER_STATUS_INVALID_REPORT_LENGTH;
}
for(Index = 0; Index < Report->ItemCount; Index++)
{
//
// get report item
//
ReportItem = &Report->Items[Index];
//
// check usage page
//
CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
//
// does usage page match
//
if (UsagePage != CurrentUsagePage)
continue;
//
// does the usage match
//
if (Usage != (ReportItem->UsageMinimum & 0xFFFF))
continue;
//
// check if the specified usage is activated
//
ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
//
// one extra shift for skipping the prepended report id
//
Data = 0;
Parser->Copy(&Data, &ReportDescriptor[ReportItem->ByteOffset +1], min(sizeof(ULONG), ReportDescriptorLength - (ReportItem->ByteOffset + 1)));
//Data = ReportDescriptor[ReportItem->ByteOffset + 1];
//
// shift data
//
Data >>= ReportItem->Shift;
//
// clear unwanted bits
//
Data &= ReportItem->Mask;
//
// store result
//
*UsageValue = Data;
return HIDPARSER_STATUS_SUCCESS;
}
//
// usage not found
//
return HIDPARSER_STATUS_USAGE_NOT_FOUND;
}
HIDPARSER_STATUS
HidParser_GetScaledUsageValueWithReport(
@ -652,11 +749,18 @@ HidParser_GetScaledUsageValueWithReport(
//
// logical boundaries are signed values
//
// FIXME: scale with physical min/max
if ((Data & ~(ReportItem->Mask >> 1)) != 0)
{
Data |= ~ReportItem->Mask;
}
}
else
{
// HACK: logical boundaries are absolute values
return HIDPARSER_STATUS_BAD_LOG_PHY_VALUES;
}
//
// store result

View file

@ -34,6 +34,8 @@ TranslateHidParserStatus(
return HIDP_STATUS_I8042_TRANS_UNKNOWN;
case HIDPARSER_STATUS_COLLECTION_NOT_FOUND:
return HIDP_STATUS_NOT_IMPLEMENTED; //FIXME
case HIDPARSER_STATUS_BAD_LOG_PHY_VALUES:
return HIDP_STATUS_BAD_LOG_PHY_VALUES;
}
DPRINT1("TranslateHidParserStatus Status %ld not implemented\n", Status);
return HIDP_STATUS_NOT_IMPLEMENTED;
@ -952,9 +954,54 @@ HidParser_GetUsageValue(
IN PCHAR Report,
IN ULONG ReportLength)
{
UNIMPLEMENTED
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
HIDPARSER_STATUS ParserStatus;
//
// FIXME: implement searching in specific collection
//
ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
if (ReportType == HidP_Input)
{
//
// input report
//
ParserStatus = HidParser_GetUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
}
else if (ReportType == HidP_Output)
{
//
// input report
//
ParserStatus = HidParser_GetUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
}
else if (ReportType == HidP_Feature)
{
//
// input report
//
ParserStatus = HidParser_GetUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, UsageValue, Report, ReportLength);
}
else
{
//
// invalid report type
//
return HIDP_STATUS_INVALID_REPORT_TYPE;
}
if (ParserStatus == HIDPARSER_STATUS_SUCCESS)
{
//
// success
//
return HIDP_STATUS_SUCCESS;
}
//
// translate error
//
return TranslateHidParserStatus(ParserStatus);
}
NTSTATUS

View file

@ -48,7 +48,8 @@ typedef enum
HIDPARSER_STATUS_INVALID_REPORT_TYPE = -6,
HIDPARSER_STATUS_BUFFER_TOO_SMALL = -7,
HIDPARSER_STATUS_USAGE_NOT_FOUND = -8,
HIDPARSER_STATUS_I8042_TRANS_UNKNOWN = -9
HIDPARSER_STATUS_I8042_TRANS_UNKNOWN = -9,
HIDPARSER_STATUS_BAD_LOG_PHY_VALUES = -10
}HIDPARSER_STATUS_CODES;
typedef struct
@ -200,6 +201,7 @@ HidParser_GetLinkCollectionNodes(
OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes,
IN OUT PULONG LinkCollectionNodesLength);
HIDAPI
NTSTATUS
NTAPI

View file

@ -327,6 +327,17 @@ HidParser_GetScaledUsageValueWithReport(
IN PCHAR ReportDescriptor,
IN ULONG ReportDescriptorLength);
HIDPARSER_STATUS
HidParser_GetUsageValueWithReport(
IN PHID_PARSER Parser,
IN PVOID CollectionContext,
IN UCHAR ReportType,
IN USAGE UsagePage,
IN USAGE Usage,
OUT PULONG UsageValue,
IN PCHAR ReportDescriptor,
IN ULONG ReportDescriptorLength);
/* parser.c */
HIDPARSER_STATUS

View file

@ -285,6 +285,11 @@ PoVolumeDevice(
IN PDEVICE_OBJECT DeviceObject
);
VOID
NTAPI
PoRemoveVolumeDevice(
IN PDEVICE_OBJECT DeviceObject);
//
// Power State routines
//

View file

@ -1035,6 +1035,9 @@ IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
/* Set the pending delete flag */
IoGetDevObjExtension(DeviceObject)->ExtensionFlags |= DOE_DELETE_PENDING;
/* Unlink with the power manager */
if (DeviceObject->Vpb) PoRemoveVolumeDevice(DeviceObject);
/* Check if the device object can be unloaded */
if (!DeviceObject->ReferenceCount) IopUnloadDevice(DeviceObject);
}

View file

@ -97,7 +97,52 @@ PoVolumeDevice(IN PDEVICE_OBJECT DeviceObject)
KeReleaseGuardedMutex(&PopVolumeLock);
}
}
VOID
NTAPI
PoRemoveVolumeDevice(IN PDEVICE_OBJECT DeviceObject)
{
PDEVICE_OBJECT_POWER_EXTENSION Dope;
PEXTENDED_DEVOBJ_EXTENSION DeviceExtension;
KIRQL OldIrql;
PAGED_CODE();
/* If the device already has the dope, return it */
DeviceExtension = IoGetDevObjExtension(DeviceObject);
if (!DeviceExtension->Dope)
{
/* no dope */
return;
}
/* Make sure we can flush safely */
KeAcquireGuardedMutex(&PopVolumeLock);
/* Get dope from device */
Dope = (PDEVICE_OBJECT_POWER_EXTENSION)DeviceExtension->Dope;
if (Dope->Volume.Flink)
{
/* Remove from volume from list */
RemoveEntryList(&Dope->Volume);
}
/* Allow flushes to go through */
KeReleaseGuardedMutex(&PopVolumeLock);
/* Now remove dope from device object */
KeAcquireSpinLock(&PopDopeGlobalLock, &OldIrql);
/* remove from dev obj */
DeviceExtension->Dope = NULL;
/* Release lock */
KeReleaseSpinLock(&PopDopeGlobalLock, OldIrql);
/* Free dope */
ExFreePoolWithTag(Dope, 'Dope');
}
VOID
NTAPI
PopFlushVolumeWorker(IN PVOID Context)

View file

@ -50,11 +50,15 @@ InitBrushImpl(VOID)
VOID
NTAPI
EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
EBRUSHOBJ_vInit(EBRUSHOBJ *pebo,
PBRUSH pbrush,
PSURFACE psurf,
COLORREF crBackgroundClr,
COLORREF crForegroundClr,
PPALETTE ppalDC)
{
ASSERT(pebo);
ASSERT(pbrush);
ASSERT(pdc);
pebo->BrushObject.flColorType = 0;
pebo->BrushObject.pvRbrush = NULL;
@ -63,20 +67,24 @@ EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
pebo->flattrs = pbrush->flAttrs;
/* Initialize 1 bpp fore and back colors */
pebo->crCurrentBack = pdc->pdcattr->crBackgroundClr;
pebo->crCurrentText = pdc->pdcattr->crForegroundClr;
pebo->crCurrentBack = crBackgroundClr;
pebo->crCurrentText = crForegroundClr;
pebo->psurfTrg = pdc->dclevel.pSurface;
pebo->psurfTrg = psurf;
/* We are initializing for a new memory DC */
if(!pebo->psurfTrg)
pebo->psurfTrg = psurfDefaultBitmap;
ASSERT(pebo->psurfTrg);
ASSERT(pebo->psurfTrg->ppal);
/* Initialize palettes */
pebo->ppalSurf = pebo->psurfTrg->ppal;
GDIOBJ_vReferenceObjectByPointer(&pebo->ppalSurf->BaseObject);
pebo->ppalDC = pdc->dclevel.ppal;
pebo->ppalDC = ppalDC;
if(!pebo->ppalDC)
pebo->ppalDC = gppalDefault;
GDIOBJ_vReferenceObjectByPointer(&pebo->ppalDC->BaseObject);
pebo->ppalDIB = NULL;
if (pbrush->flAttrs & BR_IS_NULL)
{
@ -99,6 +107,16 @@ EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
}
}
VOID
NTAPI
EBRUSHOBJ_vInitFromDC(EBRUSHOBJ *pebo,
PBRUSH pbrush, PDC pdc)
{
EBRUSHOBJ_vInit(pebo, pbrush, pdc->dclevel.pSurface,
pdc->pdcattr->crBackgroundClr, pdc->pdcattr->crForegroundClr,
pdc->dclevel.ppal);
}
VOID
FASTCALL
EBRUSHOBJ_vSetSolidRGBColor(EBRUSHOBJ *pebo, COLORREF crColor)
@ -157,13 +175,15 @@ EBRUSHOBJ_vCleanup(EBRUSHOBJ *pebo)
VOID
NTAPI
EBRUSHOBJ_vUpdate(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
EBRUSHOBJ_vUpdateFromDC(EBRUSHOBJ *pebo,
PBRUSH pbrush,
PDC pdc)
{
/* Cleanup the brush */
EBRUSHOBJ_vCleanup(pebo);
/* Reinitialize */
EBRUSHOBJ_vInit(pebo, pbrush, pdc);
EBRUSHOBJ_vInitFromDC(pebo, pbrush, pdc);
}
/**

View file

@ -600,6 +600,21 @@ EXLATEOBJ_vInitXlateFromDCs(
pexlo->ppalDstDc = pdcDst->dclevel.ppal;
}
VOID NTAPI EXLATEOBJ_vInitSrcMonoXlate(
PEXLATEOBJ pexlo,
PPALETTE ppalDst,
COLORREF crBackgroundClr,
COLORREF crForegroundClr)
{
/* Normal initialisation, with mono palette as source */
EXLATEOBJ_vInitialize(pexlo,
gppalMono,
ppalDst,
0,
crBackgroundClr,
crForegroundClr);
}
VOID
NTAPI
EXLATEOBJ_vCleanup(PEXLATEOBJ pexlo)

View file

@ -7,9 +7,7 @@
*/
#include <win32k.h>
#define NDEBUG
#include <debug.h>
DBG_DEFAULT_CHANNEL(GdiBlt);
#define ROP_USES_SOURCE(Rop) (((((Rop) & 0xCC0000) >> 2) != ((Rop) & 0x330000)) || ((((Rop) & 0xCC000000) >> 2) != ((Rop) & 0x33000000)))
#define ROP_USES_MASK(Rop) (((Rop) & 0xFF000000) != (((Rop) & 0xff0000) << 8))
@ -49,12 +47,12 @@ NtGdiAlphaBlend(
return FALSE;
}
DPRINT("Locking DCs\n");
TRACE("Locking DCs\n");
ahDC[0] = hDCDest;
ahDC[1] = hDCSrc ;
if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
{
DPRINT1("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
@ -102,7 +100,7 @@ NtGdiAlphaBlend(
}
/* Prepare DCs for blit */
DPRINT("Preparing DCs for blit\n");
TRACE("Preparing DCs for blit\n");
DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
/* Determine surfaces to be used in the bitblt */
@ -124,7 +122,7 @@ NtGdiAlphaBlend(
EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
/* Perform the alpha blend operation */
DPRINT("Performing the alpha blend\n");
TRACE("Performing the alpha blend\n");
bResult = IntEngAlphaBlend(&BitmapDest->SurfObj,
&BitmapSrc->SurfObj,
DCDest->rosdc.CombinedClip,
@ -135,7 +133,7 @@ NtGdiAlphaBlend(
EXLATEOBJ_vCleanup(&exlo);
leave :
DPRINT("Finishing blit\n");
TRACE("Finishing blit\n");
DC_vFinishBlit(DCDest, DCSrc);
GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
GDIOBJ_vUnlockObject(&DCDest->BaseObject);
@ -197,12 +195,12 @@ NtGdiTransparentBlt(
BOOL Ret = FALSE;
EXLATEOBJ exlo;
DPRINT("Locking DCs\n");
TRACE("Locking DCs\n");
ahDC[0] = hdcDst;
ahDC[1] = hdcSrc ;
if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
{
DPRINT1("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc);
WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc);
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
@ -343,7 +341,7 @@ NtGdiMaskBlt(
}
else if(psurfMask)
{
DPRINT1("Getting Mask bitmap without needing it?\n");
WARN("Getting Mask bitmap without needing it?\n");
SURFACE_ShareUnlockSurface(psurfMask);
psurfMask = NULL;
}
@ -351,12 +349,12 @@ NtGdiMaskBlt(
MaskPoint.y = yMask;
/* Take care of source and destination bitmap */
DPRINT("Locking DCs\n");
TRACE("Locking DCs\n");
ahDC[0] = hdcDest;
ahDC[1] = UsesSource ? hdcSrc : NULL;
if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
{
DPRINT1("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDest, hdcSrc);
WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDest, hdcSrc);
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
@ -367,7 +365,7 @@ NtGdiMaskBlt(
if (NULL == DCDest)
{
if(DCSrc) DC_UnlockDc(DCSrc);
DPRINT("Invalid destination dc handle (0x%p) passed to NtGdiBitBlt\n", hdcDest);
WARN("Invalid destination dc handle (0x%p) passed to NtGdiBitBlt\n", hdcDest);
return FALSE;
}
@ -497,7 +495,7 @@ NtGdiPlgBlt(
IN INT yMask,
IN DWORD crBackColor)
{
UNIMPLEMENTED;
FIXME("NtGdiPlgBlt: unimplemented.\n");
return FALSE;
}
@ -558,7 +556,7 @@ GreStretchBltMask(
ahDC[2] = UsesMask ? hDCMask : NULL;
if (!GDIOBJ_bLockMultipleObjects(3, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
{
DPRINT1("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to GreStretchBltMask\n", hDCDest, hDCSrc);
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
@ -651,7 +649,7 @@ GreStretchBltMask(
(BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
{
DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
WARN("%dx%d mask is smaller than %dx%d bitmap\n",
BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
WidthSrc, HeightSrc);
EXLATEOBJ_vCleanup(&exlo);
@ -853,7 +851,7 @@ IntGdiPolyPatBlt(
if (pbrush != NULL)
{
/* Initialize a brush object */
EBRUSHOBJ_vInit(&eboFill, pbrush, pdc);
EBRUSHOBJ_vInitFromDC(&eboFill, pbrush, pdc);
IntPatBlt(
pdc,

View file

@ -98,6 +98,8 @@ BOOL NTAPI BRUSH_Cleanup(PVOID ObjectBody);
extern HSURF gahsurfHatch[HS_DDI_MAX];
struct _SURFACE;
struct _PALETTE;
struct _DC;
INIT_FUNCTION
@ -107,7 +109,11 @@ InitBrushImpl(VOID);
VOID
NTAPI
EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _DC *);
EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _SURFACE *, COLORREF, COLORREF, struct _PALETTE *);
VOID
NTAPI
EBRUSHOBJ_vInitFromDC(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _DC *);
VOID
FASTCALL
@ -115,7 +121,7 @@ EBRUSHOBJ_vSetSolidRGBColor(EBRUSHOBJ *pebo, COLORREF crColor);
VOID
NTAPI
EBRUSHOBJ_vUpdate(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _DC *pdc);
EBRUSHOBJ_vUpdateFromDC(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _DC *);
BOOL
NTAPI

View file

@ -270,10 +270,10 @@ DC_vInitDc(
pdc->dcattr.ptlBrushOrigin = pdc->dclevel.ptlBrushOrigin;
/* Initialize EBRUSHOBJs */
EBRUSHOBJ_vInit(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
EBRUSHOBJ_vInit(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
EBRUSHOBJ_vInit(&pdc->eboText, pbrDefaultBrush, pdc);
EBRUSHOBJ_vInit(&pdc->eboBackground, pbrDefaultBrush, pdc);
EBRUSHOBJ_vInitFromDC(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
EBRUSHOBJ_vInitFromDC(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
EBRUSHOBJ_vInitFromDC(&pdc->eboText, pbrDefaultBrush, pdc);
EBRUSHOBJ_vInitFromDC(&pdc->eboBackground, pbrDefaultBrush, pdc);
/* Setup fill data */
pdc->dcattr.jROP2 = R2_COPYPEN;

View file

@ -43,7 +43,7 @@ DC_vUpdateFillBrush(PDC pdc)
if (pdcattr->ulDirty_ & DIRTY_FILL)
{
/* Update eboFill */
EBRUSHOBJ_vUpdate(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
EBRUSHOBJ_vUpdateFromDC(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
}
/* Check for DC brush */
@ -90,7 +90,7 @@ DC_vUpdateLineBrush(PDC pdc)
if (pdcattr->ulDirty_ & DIRTY_LINE)
{
/* Update eboLine */
EBRUSHOBJ_vUpdate(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
EBRUSHOBJ_vUpdateFromDC(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
}
/* Check for DC pen */
@ -113,7 +113,7 @@ DC_vUpdateTextBrush(PDC pdc)
/* Timo : The text brush should never be changed.
* Jérôme : Yeah, but its palette must be updated anyway! */
if(pdcattr->ulDirty_ & DIRTY_TEXT)
EBRUSHOBJ_vUpdate(&pdc->eboText, pbrDefaultBrush, pdc);
EBRUSHOBJ_vUpdateFromDC(&pdc->eboText, pbrDefaultBrush, pdc);
/* Update the eboText's solid color */
EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboText, pdcattr->crForegroundClr);
@ -129,7 +129,7 @@ DC_vUpdateBackgroundBrush(PDC pdc)
PDC_ATTR pdcattr = pdc->pdcattr;
if(pdcattr->ulDirty_ & DIRTY_BACKGROUND)
EBRUSHOBJ_vUpdate(&pdc->eboBackground, pbrDefaultBrush, pdc);
EBRUSHOBJ_vUpdateFromDC(&pdc->eboBackground, pbrDefaultBrush, pdc);
/* Update the eboBackground's solid color */
EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboBackground, pdcattr->crBackgroundClr);

View file

@ -1042,7 +1042,14 @@ CLEANUP:
}
#endif
/* Mostly inspired from wine code */
/* Mostly inspired from wine code.
* We use low level functions because:
* - at this point, the icon bitmap could have a different bit depth than the DC,
* making it thus impossible to use NtCreateCompatibleDC and selecting the bitmap.
* This happens after a mode setting change.
* - it avoids massive GDI objects locking when only the destination surface needs it.
* - It makes (small) performance gains.
*/
BOOL
UserDrawIconEx(
HDC hDc,
@ -1055,128 +1062,220 @@ UserDrawIconEx(
HBRUSH hbrFlickerFreeDraw,
UINT diFlags)
{
PSURFACE psurfDest, psurfMask, psurfColor, psurfOffScreen;
PDC pdc = NULL;
BOOL Ret = FALSE;
HBITMAP hbmMask, hbmColor;
BITMAP bmpColor, bm;
BOOL DoFlickerFree;
INT iOldBkColor = 0, iOldTxtColor = 0;
HDC hMemDC, hDestDC = hDc;
HGDIOBJ hOldOffBrush = 0;
HGDIOBJ hOldOffBmp = 0;
HBITMAP hTmpBmp = 0, hOffBmp = 0;
BOOL bAlpha = FALSE;
INT x=xLeft, y=yTop;
BOOL bOffScreen, bAlpha = FALSE;
RECTL rcDest, rcSrc;
CLIPOBJ* pdcClipObj = NULL;
EXLATEOBJ exlo;
/* Stupid case */
if((diFlags & DI_NORMAL) == 0)
{
ERR("DrawIconEx called without mask or color bitmap to draw.\n");
return FALSE;
}
hbmMask = pIcon->IconInfo.hbmMask;
hbmColor = pIcon->IconInfo.hbmColor;
if (istepIfAniCur)
ERR("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
if (!hbmMask || !GreGetObject(hbmMask, sizeof(BITMAP), (PVOID)&bm))
/*
* Get our objects.
* Shared locks are enough, we are only reading those bitmaps
*/
psurfMask = SURFACE_ShareLockSurface(hbmMask);
if(psurfMask == NULL)
{
ERR("Unable to lock the mask surface.\n");
return FALSE;
}
if (hbmColor && !GreGetObject(hbmColor, sizeof(BITMAP), (PVOID)&bmpColor))
/* Color bitmap is not mandatory */
if(hbmColor == NULL)
{
/* But then the mask bitmap must have the information in it's bottom half */
ASSERT(psurfMask->SurfObj.sizlBitmap.cy == 2*pIcon->Size.cy);
psurfColor = NULL;
}
else if ((psurfColor = SURFACE_ShareLockSurface(hbmColor)) == NULL)
{
ERR("Unable to lock the color bitmap.\n");
SURFACE_ShareUnlockSurface(psurfMask);
return FALSE;
}
if(!(hMemDC = NtGdiCreateCompatibleDC(hDc)))
{
ERR("NtGdiCreateCompatibleDC failed!\n");
return FALSE;
}
/* Set source rect */
RECTL_vSetRect(&rcSrc, 0, 0, pIcon->Size.cx, pIcon->Size.cy);
/* Check for alpha */
if (hbmColor
&& (bmpColor.bmBitsPixel == 32)
&& (diFlags & DI_IMAGE))
if (psurfColor &&
(psurfColor->SurfObj.iBitmapFormat == BMF_32BPP) &&
(diFlags & DI_IMAGE))
{
SURFACE *psurfOff = NULL;
PFN_DIB_GetPixel fnSource_GetPixel = NULL;
INT i, j;
/* In order to correctly display 32 bit icons Windows first scans the image,
because information about transparency is not stored in any image's headers */
psurfOff = SURFACE_ShareLockSurface(hbmColor);
if (psurfOff)
fnSource_GetPixel = DibFunctionsForBitmapFormat[BMF_32BPP].DIB_GetPixel;
for (i = 0; i < psurfColor->SurfObj.sizlBitmap.cx; i++)
{
fnSource_GetPixel = DibFunctionsForBitmapFormat[psurfOff->SurfObj.iBitmapFormat].DIB_GetPixel;
if (fnSource_GetPixel)
for (j = 0; j < psurfColor->SurfObj.sizlBitmap.cy; j++)
{
for (i = 0; i < psurfOff->SurfObj.sizlBitmap.cx; i++)
{
for (j = 0; j < psurfOff->SurfObj.sizlBitmap.cy; j++)
{
bAlpha = ((BYTE)(fnSource_GetPixel(&psurfOff->SurfObj, i, j) >> 24) & 0xff);
if (bAlpha)
break;
}
if (bAlpha)
break;
}
bAlpha = ((BYTE)(fnSource_GetPixel(&psurfColor->SurfObj, i, j) >> 24) & 0xff);
if (bAlpha)
break;
}
SURFACE_ShareUnlockSurface(psurfOff);
if (bAlpha)
break;
}
}
/* Fix width parameter, if needed */
if (!cxWidth)
cxWidth = ((diFlags & DI_DEFAULTSIZE) ?
UserGetSystemMetrics(SM_CXICON) : pIcon->Size.cx);
if (!cyHeight)
cyHeight = ((diFlags & DI_DEFAULTSIZE) ?
UserGetSystemMetrics(SM_CYICON) : pIcon->Size.cy);
DoFlickerFree = (hbrFlickerFreeDraw &&
(GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH));
if (DoFlickerFree)
{
hDestDC = NtGdiCreateCompatibleDC(hDc);
if(!hDestDC)
{
ERR("NtGdiCreateCompatibleDC failed!\n");
Ret = FALSE;
goto Cleanup ;
}
hOffBmp = NtGdiCreateCompatibleBitmap(hDc, cxWidth, cyHeight);
if(!hOffBmp)
{
ERR("NtGdiCreateCompatibleBitmap failed!\n");
goto Cleanup ;
}
hOldOffBmp = NtGdiSelectBitmap(hDestDC, hOffBmp);
hOldOffBrush = NtGdiSelectBrush(hDestDC, hbrFlickerFreeDraw);
NtGdiPatBlt(hDestDC, 0, 0, cxWidth, cyHeight, PATCOPY);
NtGdiSelectBrush(hDestDC, hOldOffBrush);
x=y=0;
if(diFlags & DI_DEFAULTSIZE)
cxWidth = pIcon->IconInfo.fIcon ?
UserGetSystemMetrics(SM_CXICON) : UserGetSystemMetrics(SM_CXCURSOR);
else
cxWidth = pIcon->Size.cx;
}
/* Fix height parameter, if needed */
if (!cyHeight)
{
if(diFlags & DI_DEFAULTSIZE)
cyHeight = pIcon->IconInfo.fIcon ?
UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR);
else
cyHeight = pIcon->Size.cy;
}
/* Set Background/foreground colors */
iOldTxtColor = IntGdiSetTextColor(hDc, 0); // Black
iOldBkColor = IntGdiSetBkColor(hDc, 0x00FFFFFF); // White
/* Should we render off-screen? */
bOffScreen = hbrFlickerFreeDraw && (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH);
if (bOffScreen)
{
/* Yes: Allocate and paint the offscreen surface */
EBRUSHOBJ eboFill;
PBRUSH pbrush = BRUSH_ShareLockBrush(hbrFlickerFreeDraw);
TRACE("Performing off-screen rendering.\n");
if(!pbrush)
{
ERR("Failed to get brush object.\n");
SURFACE_ShareUnlockSurface(psurfMask);
if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
return FALSE;
}
psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP,
cxWidth, cyHeight, psurfColor->SurfObj.iBitmapFormat,
0, 0, NULL);
if(!psurfOffScreen)
{
ERR("Failed to allocate the off-screen surface.\n");
SURFACE_ShareUnlockSurface(psurfMask);
if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
BRUSH_ShareUnlockBrush(pbrush);
return FALSE;
}
/* Paint the brush */
EBRUSHOBJ_vInit(&eboFill, pbrush, psurfOffScreen, 0x00FFFFFF, 0, NULL);
RECTL_vSetRect(&rcDest, 0, 0, cxWidth, cyHeight);
Ret = IntEngBitBlt(&psurfOffScreen->SurfObj,
NULL,
NULL,
NULL,
NULL,
&rcDest,
NULL,
NULL,
&eboFill.BrushObject,
&pbrush->ptOrigin,
ROP4_PATCOPY);
/* Clean up everything */
EBRUSHOBJ_vCleanup(&eboFill);
BRUSH_ShareUnlockBrush(pbrush);
if(!Ret)
{
ERR("Failed to paint the off-screen surface.\n");
SURFACE_ShareUnlockSurface(psurfMask);
if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject);
return FALSE;
}
/* We now have our destination surface */
psurfDest = psurfOffScreen;
}
else
{
/* We directly draw to the DC */
TRACE("Performing on screen rendering.\n");
psurfOffScreen = NULL;
pdc = DC_LockDc(hDc);
if(!pdc)
{
ERR("Could not lock the destination DC.\n");
SURFACE_ShareUnlockSurface(psurfMask);
if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
return FALSE;
}
/* Calculate destination rectangle */
RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight);
IntLPtoDP(pdc, (LPPOINT)&rcDest, 2);
RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
/* Prepare the underlying surface */
DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest);
/* Get the clip object */
pdcClipObj = pdc->rosdc.CombinedClip;
/* We now have our destination surface and rectangle */
psurfDest = pdc->dclevel.pSurface;
if(psurfDest == NULL)
{
/* Empty DC */
DC_vFinishBlit(pdc, NULL);
DC_UnlockDc(pdc);
SURFACE_ShareUnlockSurface(psurfMask);
if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
return FALSE;
}
}
/* Now do the rendering */
if(bAlpha && (diFlags & DI_IMAGE))
{
BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } };
BYTE Alpha;
INT i, j;
PSURFACE psurf;
PSURFACE psurf = NULL;
PBYTE ptr ;
HBITMAP hMemBmp = NULL;
HBITMAP hsurfCopy = NULL;
hMemBmp = BITMAP_CopyBitmap(hbmColor);
if(!hMemBmp)
hsurfCopy = BITMAP_CopyBitmap(hbmColor);
if(!hsurfCopy)
{
ERR("BITMAP_CopyBitmap failed!");
goto CleanupAlpha;
}
psurf = SURFACE_ShareLockSurface(hMemBmp);
psurf = SURFACE_ShareLockSurface(hsurfCopy);
if(!psurf)
{
ERR("SURFACE_LockSurface failed!\n");
@ -1197,109 +1296,181 @@ UserDrawIconEx(
ptr += 4;
}
}
SURFACE_ShareUnlockSurface(psurf);
hTmpBmp = NtGdiSelectBitmap(hMemDC, hMemBmp);
Ret = NtGdiAlphaBlend(hDestDC,
x,
y,
cxWidth,
cyHeight,
hMemDC,
0,
0,
pIcon->Size.cx,
pIcon->Size.cy,
pixelblend,
NULL);
NtGdiSelectBitmap(hMemDC, hTmpBmp);
/* Initialize color translation object */
EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xFFFFFFFF, 0xFFFFFFFF, 0);
/* Now do it */
Ret = IntEngAlphaBlend(&psurfDest->SurfObj,
&psurf->SurfObj,
pdcClipObj,
&exlo.xlo,
&rcDest,
&rcSrc,
&blendobj);
EXLATEOBJ_vCleanup(&exlo);
CleanupAlpha:
if(hMemBmp) NtGdiDeleteObjectApp(hMemBmp);
if(psurf) SURFACE_ShareUnlockSurface(psurf);
if(hsurfCopy) NtGdiDeleteObjectApp(hsurfCopy);
if(Ret) goto done;
ERR("NtGdiAlphaBlend failed!\n");
}
if (diFlags & DI_MASK)
{
DWORD rop = (diFlags & DI_IMAGE) ? SRCAND : SRCCOPY;
hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
NtGdiStretchBlt(hDestDC,
x,
y,
cxWidth,
cyHeight,
hMemDC,
0,
0,
pIcon->Size.cx,
pIcon->Size.cy,
rop,
0);
NtGdiSelectBitmap(hMemDC, hTmpBmp);
DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY;
EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0);
Ret = IntEngStretchBlt(&psurfDest->SurfObj,
&psurfMask->SurfObj,
NULL,
pdcClipObj,
&exlo.xlo,
NULL,
&rcDest,
&rcSrc,
NULL,
NULL,
NULL,
rop4);
EXLATEOBJ_vCleanup(&exlo);
if(!Ret)
{
ERR("Failed to mask the bitmap data.\n");
goto Cleanup;
}
}
if(diFlags & DI_IMAGE)
{
if (hbmColor)
if (psurfColor)
{
DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmColor);
NtGdiStretchBlt(hDestDC,
x,
y,
cxWidth,
cyHeight,
hMemDC,
0,
0,
pIcon->Size.cx,
pIcon->Size.cy,
rop,
0);
NtGdiSelectBitmap(hMemDC, hTmpBmp);
DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY ;
EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0);
Ret = IntEngStretchBlt(&psurfDest->SurfObj,
&psurfColor->SurfObj,
NULL,
pdcClipObj,
&exlo.xlo,
NULL,
&rcDest,
&rcSrc,
NULL,
NULL,
NULL,
rop4);
EXLATEOBJ_vCleanup(&exlo);
if(!Ret)
{
ERR("Failed to render the icon bitmap.\n");
goto Cleanup;
}
}
else
{
/* Mask bitmap holds the information in its second half */
DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
NtGdiStretchBlt(hDestDC,
x,
y,
cxWidth,
cyHeight,
hMemDC,
0,
pIcon->Size.cy,
pIcon->Size.cx,
pIcon->Size.cy,
rop,
0);
NtGdiSelectBitmap(hMemDC, hTmpBmp);
/* Mask bitmap holds the information in its bottom half */
DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY;
RECTL_vOffsetRect(&rcSrc, 0, pIcon->Size.cy);
EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0);
Ret = IntEngStretchBlt(&psurfDest->SurfObj,
&psurfMask->SurfObj,
NULL,
pdcClipObj,
&exlo.xlo,
NULL,
&rcDest,
&rcSrc,
NULL,
NULL,
NULL,
rop4);
EXLATEOBJ_vCleanup(&exlo);
if(!Ret)
{
ERR("Failed to render the icon bitmap.\n");
goto Cleanup;
}
}
}
done:
if(hDestDC != hDc)
/* We're done. Was it a double buffered draw ? */
if(bOffScreen)
{
NtGdiBitBlt(hDc, xLeft, yTop, cxWidth, cyHeight, hDestDC, 0, 0, SRCCOPY, 0, 0);
/* Yes. Draw it back to our DC */
POINTL ptSrc = {0, 0};
pdc = DC_LockDc(hDc);
if(!pdc)
{
ERR("Could not lock the destination DC.\n");
return FALSE;
}
/* Calculate destination rectangle */
RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight);
IntLPtoDP(pdc, (LPPOINT)&rcDest, 2);
RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
/* Prepare the underlying surface */
DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest);
/* Get the clip object */
pdcClipObj = pdc->rosdc.CombinedClip;
/* We now have our destination surface and rectangle */
psurfDest = pdc->dclevel.pSurface;
if(!psurfDest)
{
/* So, you did all of this for an empty DC. */
DC_UnlockDc(pdc);
goto Cleanup2;
}
/* Color translation */
EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0);
/* Blt it! */
Ret = IntEngBitBlt(&psurfDest->SurfObj,
&psurfOffScreen->SurfObj,
NULL,
pdcClipObj,
&exlo.xlo,
&rcDest,
&ptSrc,
NULL,
NULL,
NULL,
ROP4_SRCCOPY);
EXLATEOBJ_vCleanup(&exlo);
}
/* Restore foreground and background colors */
IntGdiSetBkColor(hDc, iOldBkColor);
IntGdiSetTextColor(hDc, iOldTxtColor);
Ret = TRUE ;
Cleanup:
NtGdiDeleteObjectApp(hMemDC);
if(hDestDC != hDc)
if(pdc)
{
if(hOldOffBmp) NtGdiSelectBitmap(hDestDC, hOldOffBmp);
NtGdiDeleteObjectApp(hDestDC);
if(hOffBmp) NtGdiDeleteObjectApp(hOffBmp);
DC_vFinishBlit(pdc, NULL);
DC_UnlockDc(pdc);
}
Cleanup2:
/* Delete off screen rendering surface */
if(psurfOffScreen)
GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject);
/* Unlock other surfaces */
SURFACE_ShareUnlockSurface(psurfMask);
if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
return Ret;
}