diff --git a/boot/bootdata/hivesys_amd64.inf b/boot/bootdata/hivesys_amd64.inf index 2149d3b5d83..f3cc661df7d 100644 --- a/boot/bootdata/hivesys_amd64.inf +++ b/boot/bootdata/hivesys_amd64.inf @@ -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" diff --git a/boot/bootdata/hivesys_arm.inf b/boot/bootdata/hivesys_arm.inf index cec534fe973..3fe79869cdd 100644 --- a/boot/bootdata/hivesys_arm.inf +++ b/boot/bootdata/hivesys_arm.inf @@ -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" diff --git a/boot/bootdata/hivesys_i386.inf b/boot/bootdata/hivesys_i386.inf index 2149d3b5d83..f3cc661df7d 100644 --- a/boot/bootdata/hivesys_i386.inf +++ b/boot/bootdata/hivesys_i386.inf @@ -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" diff --git a/dll/win32/lsasrv/CMakeLists.txt b/dll/win32/lsasrv/CMakeLists.txt index 90c7b5e0cf7..28d55339657 100644 --- a/dll/win32/lsasrv/CMakeLists.txt +++ b/dll/win32/lsasrv/CMakeLists.txt @@ -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 diff --git a/dll/win32/lsasrv/sids.c b/dll/win32/lsasrv/lookup.c similarity index 89% rename from dll/win32/lsasrv/sids.c rename to dll/win32/lsasrv/lookup.c index b36397018f0..3cc49738758 100644 --- a/dll/win32/lsasrv/sids.c +++ b/dll/win32/lsasrv/lookup.c @@ -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); diff --git a/dll/win32/lsasrv/lsasrv.h b/dll/win32/lsasrv/lsasrv.h index 720df26a838..5f18e5a12f8 100644 --- a/dll/win32/lsasrv/lsasrv.h +++ b/dll/win32/lsasrv/lsasrv.h @@ -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 */ diff --git a/dll/win32/samlib/samlib.c b/dll/win32/samlib/samlib.c index 7f07d5aa9a5..56071964299 100644 --- a/dll/win32/samlib/samlib.c +++ b/dll/win32/samlib/samlib.c @@ -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) diff --git a/dll/win32/samlib/samlib.spec b/dll/win32/samlib/samlib.spec index acdb6959397..0176a0c0a68 100644 --- a/dll/win32/samlib/samlib.spec +++ b/dll/win32/samlib/samlib.spec @@ -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 diff --git a/dll/win32/shell32/iconcache.cpp b/dll/win32/shell32/iconcache.cpp index b4f0076faee..242b5919f26 100644 --- a/dll/win32/shell32/iconcache.cpp +++ b/dll/win32/shell32/iconcache.cpp @@ -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; ibmiHeader.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; ibmiHeader.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 * diff --git a/drivers/hid/hidparse/hidparse.c b/drivers/hid/hidparse/hidparse.c index d44310630d8..4254fd7c633 100644 --- a/drivers/hid/hidparse/hidparse.c +++ b/drivers/hid/hidparse/hidparse.c @@ -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 ( diff --git a/drivers/hid/mouhid/mouhid.c b/drivers/hid/mouhid/mouhid.c index b713b70f3dc..6ba3007048f 100644 --- a/drivers/hid/mouhid/mouhid.c +++ b/drivers/hid/mouhid/mouhid.c @@ -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; diff --git a/drivers/hid/mouhid/mouhid.h b/drivers/hid/mouhid/mouhid.h index 78048fdce5d..e177a2ff985 100644 --- a/drivers/hid/mouhid/mouhid.h +++ b/drivers/hid/mouhid/mouhid.h @@ -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 diff --git a/drivers/usb/usbd/usbd.c b/drivers/usb/usbd/usbd.c index df273ee3f8a..958f017f3da 100644 --- a/drivers/usb/usbd/usbd.c +++ b/drivers/usb/usbd/usbd.c @@ -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); diff --git a/drivers/usb/usbhub/fdo.c b/drivers/usb/usbhub/fdo.c index ec56674fc09..65c529ccbe8 100644 --- a/drivers/usb/usbhub/fdo.c +++ b/drivers/usb/usbhub/fdo.c @@ -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; diff --git a/drivers/usb/usbhub/pdo.c b/drivers/usb/usbhub/pdo.c index 939a9f3f816..6c561b99662 100644 --- a/drivers/usb/usbhub/pdo.c +++ b/drivers/usb/usbhub/pdo.c @@ -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); diff --git a/drivers/usb/usbhub/usbhub.h b/drivers/usb/usbhub/usbhub.h index 23337755e74..52d62e2540b 100644 --- a/drivers/usb/usbhub/usbhub.h +++ b/drivers/usb/usbhub/usbhub.h @@ -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 diff --git a/drivers/usb/usbstor/fdo.c b/drivers/usb/usbstor/fdo.c index 07518428037..a9f408da099 100644 --- a/drivers/usb/usbstor/fdo.c +++ b/drivers/usb/usbstor/fdo.c @@ -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; } diff --git a/drivers/usb/usbstor/pdo.c b/drivers/usb/usbstor/pdo.c index 9e293df80a6..f7a2a654789 100644 --- a/drivers/usb/usbstor/pdo.c +++ b/drivers/usb/usbstor/pdo.c @@ -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 diff --git a/drivers/usb/usbstor/usbstor.h b/drivers/usb/usbstor/usbstor.h index 29ef1ce6bd6..3fb4d3cc642 100644 --- a/drivers/usb/usbstor/usbstor.h +++ b/drivers/usb/usbstor/usbstor.h @@ -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); //--------------------------------------------------------------------- // diff --git a/include/ddk/ntsam.h b/include/ddk/ntsam.h index 69b5e345356..cb0af846bf3 100644 --- a/include/ddk/ntsam.h +++ b/include/ddk/ntsam.h @@ -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); diff --git a/include/reactos/idl/sam.idl b/include/reactos/idl/sam.idl index 3ff5467f808..96f1640ec94 100644 --- a/include/reactos/idl/sam.idl +++ b/include/reactos/idl/sam.idl @@ -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 { diff --git a/include/reactos/wine/unicode.h b/include/reactos/wine/unicode.h index 60daf9b42df..2550cf40653 100644 --- a/include/reactos/wine/unicode.h +++ b/include/reactos/wine/unicode.h @@ -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 diff --git a/lib/drivers/hidparser/api.c b/lib/drivers/hidparser/api.c index 1420da7ffb7..ee77899ae21 100644 --- a/lib/drivers/hidparser/api.c +++ b/lib/drivers/hidparser/api.c @@ -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 diff --git a/lib/drivers/hidparser/hidparser.c b/lib/drivers/hidparser/hidparser.c index c38b8e1c978..cc27cd8c10c 100644 --- a/lib/drivers/hidparser/hidparser.c +++ b/lib/drivers/hidparser/hidparser.c @@ -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 diff --git a/lib/drivers/hidparser/hidparser.h b/lib/drivers/hidparser/hidparser.h index 425c20899e1..ed7a616b638 100644 --- a/lib/drivers/hidparser/hidparser.h +++ b/lib/drivers/hidparser/hidparser.h @@ -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 diff --git a/lib/drivers/hidparser/parser.h b/lib/drivers/hidparser/parser.h index ef0d7f3e421..a7126df678d 100644 --- a/lib/drivers/hidparser/parser.h +++ b/lib/drivers/hidparser/parser.h @@ -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 diff --git a/ntoskrnl/include/internal/po.h b/ntoskrnl/include/internal/po.h index dcc4d0dbcbb..11891202787 100644 --- a/ntoskrnl/include/internal/po.h +++ b/ntoskrnl/include/internal/po.h @@ -285,6 +285,11 @@ PoVolumeDevice( IN PDEVICE_OBJECT DeviceObject ); +VOID +NTAPI +PoRemoveVolumeDevice( + IN PDEVICE_OBJECT DeviceObject); + // // Power State routines // diff --git a/ntoskrnl/io/iomgr/device.c b/ntoskrnl/io/iomgr/device.c index 0b1a8861fb4..a0e19615056 100644 --- a/ntoskrnl/io/iomgr/device.c +++ b/ntoskrnl/io/iomgr/device.c @@ -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); } diff --git a/ntoskrnl/po/povolume.c b/ntoskrnl/po/povolume.c index 15aaebf7586..77003029a43 100644 --- a/ntoskrnl/po/povolume.c +++ b/ntoskrnl/po/povolume.c @@ -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) diff --git a/win32ss/gdi/eng/engbrush.c b/win32ss/gdi/eng/engbrush.c index fcc03f1bce2..45acd94b13e 100644 --- a/win32ss/gdi/eng/engbrush.c +++ b/win32ss/gdi/eng/engbrush.c @@ -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); } /** diff --git a/win32ss/gdi/eng/xlateobj.c b/win32ss/gdi/eng/xlateobj.c index f9c27d84b36..98a1b0248a3 100644 --- a/win32ss/gdi/eng/xlateobj.c +++ b/win32ss/gdi/eng/xlateobj.c @@ -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) diff --git a/win32ss/gdi/ntgdi/bitblt.c b/win32ss/gdi/ntgdi/bitblt.c index e38b1c56f70..7c5dba4f431 100644 --- a/win32ss/gdi/ntgdi/bitblt.c +++ b/win32ss/gdi/ntgdi/bitblt.c @@ -7,9 +7,7 @@ */ #include - -#define NDEBUG -#include +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, diff --git a/win32ss/gdi/ntgdi/brush.h b/win32ss/gdi/ntgdi/brush.h index 78d5a10d4ed..69288aea614 100644 --- a/win32ss/gdi/ntgdi/brush.h +++ b/win32ss/gdi/ntgdi/brush.h @@ -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 diff --git a/win32ss/gdi/ntgdi/dclife.c b/win32ss/gdi/ntgdi/dclife.c index 261cb16c343..66c709be861 100644 --- a/win32ss/gdi/ntgdi/dclife.c +++ b/win32ss/gdi/ntgdi/dclife.c @@ -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; diff --git a/win32ss/gdi/ntgdi/dcobjs.c b/win32ss/gdi/ntgdi/dcobjs.c index 370953f0c9d..db9bdbc8e06 100644 --- a/win32ss/gdi/ntgdi/dcobjs.c +++ b/win32ss/gdi/ntgdi/dcobjs.c @@ -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); diff --git a/win32ss/user/ntuser/cursoricon.c b/win32ss/user/ntuser/cursoricon.c index 91f41666181..4be2e643144 100644 --- a/win32ss/user/ntuser/cursoricon.c +++ b/win32ss/user/ntuser/cursoricon.c @@ -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; }