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"
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"
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"
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
/*
* 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
{
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;
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;
*p = SubAuthorities[i];
}
- RtlInitUnicodeString(&SidEntry->Name,
- Name);
+ RtlInitUnicodeString(&SidEntry->AccountName,
+ AccountName);
- RtlInitUnicodeString(&SidEntry->Domain,
- Domain);
+ RtlInitUnicodeString(&SidEntry->DomainName,
+ DomainName);
SidEntry->Use = Use;
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,
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,
PWELL_KNOWN_SID
-LsapLookupWellKnownName(PUNICODE_STRING Name)
+LsapLookupIsolatedWellKnownName(PUNICODE_STRING AccountName)
+{
+ 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))
+ {
+ return Ptr;
+ }
+
+ ListEntry = ListEntry->Flink;
+ }
+
+ return NULL;
+}
+
+
+PWELL_KNOWN_SID
+LsapLookupFullyQualifiedWellKnownName(PUNICODE_STRING AccountName,
+ PUNICODE_STRING DomainName)
{
PLIST_ENTRY ListEntry;
PWELL_KNOWN_SID Ptr;
Ptr = CONTAINING_RECORD(ListEntry,
WELL_KNOWN_SID,
ListEntry);
- if (RtlEqualUnicodeString(Name, &Ptr->Name, TRUE))
+ if (RtlEqualUnicodeString(AccountName, &Ptr->AccountName, TRUE) &&
+ RtlEqualUnicodeString(DomainName, &Ptr->DomainName, TRUE))
{
return Ptr;
}
}
+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,
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))
}
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))
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;
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;
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;
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;
}
+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,
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],
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;
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],
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;
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;
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,
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;
+ }
+
+ RtlCopyMemory(NamesBuffer[i].Name.Buffer, ptr->AccountName.Buffer, ptr->AccountName.MaximumLength);
- 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))
}
-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,
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);
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);
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 */
}
+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)
}
+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,
}
+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,
}
+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,
}
+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,
}
+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)
@ stdcall SamAddMemberToAlias(ptr ptr)
-@ stub SamAddMemberToGroup
-@ stub SamAddMultipleMembersToAlias
+@ stdcall SamAddMemberToGroup(ptr long long)
+@ stdcall SamAddMultipleMembersToAlias(ptr ptr long)
@ stub SamChangePasswordUser2
@ stub SamChangePasswordUser3
@ stub SamChangePasswordUser
@ 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)
@ 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)
@ 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
* 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;
-
- /* Get information about the source icon and shortcut overlay */
- if (! GetIconInfo(SourceIcon, &SourceIconInfo)
- || 0 == GetObjectW(SourceIconInfo.hbmColor, sizeof(BITMAP), &SourceBitmapInfo))
+ ZeroMemory(&ShortcutIconInfo, sizeof(ShortcutIconInfo));
+ ZeroMemory(&TargetIconInfo, sizeof(TargetIconInfo));
+
+ /* 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)
+ {
+ /* Maybe we'll support this at some point */
+ FIXME("1bpp icon wants its overlay!\n");
+ goto fail;
+ }
+
+ if(!GetObjectW(TargetIconInfo.hbmColor, sizeof(BITMAP), &TargetBitmapInfo))
{
- return NULL;
+ goto fail;
}
/* search for the shortcut icon only once */
} 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);
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) ||
- NULL == SelectObject(TargetDC, TargetIconInfo.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)
{
- goto fail;
+ BOOL add_alpha;
+ BYTE buffer[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
+ BITMAPINFO* lpbmi = (BITMAPINFO*)buffer;
+ PVOID bits;
+ PULONG pixel;
+ INT i, j;
+
+ /* Find if the source bitmap has an alpha channel */
+ if(TargetBitmapInfo.bmBitsPixel != 32) add_alpha = FALSE;
+ else
+ {
+ ZeroMemory(buffer, sizeof(buffer));
+ lpbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ lpbmi->bmiHeader.biWidth = TargetBitmapInfo.bmWidth;
+ lpbmi->bmiHeader.biHeight = TargetBitmapInfo.bmHeight;
+ lpbmi->bmiHeader.biPlanes = 1;
+ lpbmi->bmiHeader.biBitCount = 32;
+
+ bits = HeapAlloc(GetProcessHeap(), 0, TargetBitmapInfo.bmHeight * TargetBitmapInfo.bmWidthBytes);
+
+ if(!bits) goto fail;
+
+ if(!GetDIBits(TargetDC, TargetIconInfo.hbmColor, 0, TargetBitmapInfo.bmHeight, bits, lpbmi, DIB_RGB_COLORS))
+ {
+ ERR("GetBIBits failed!\n");
+ HeapFree(GetProcessHeap(), 0, bits);
+ goto fail;
+ }
+
+ i = j = 0;
+ pixel = (PULONG)bits;
+
+ for(i=0; i<TargetBitmapInfo.bmHeight; i++)
+ {
+ for(j=0; j<TargetBitmapInfo.bmWidth; j++)
+ {
+ add_alpha = (*pixel++ & 0xFF000000) != 0;
+ if(add_alpha) break;
+ }
+ if(add_alpha) break;
+ }
+ HeapFree(GetProcessHeap(), 0, bits);
+ }
+
+ /* Allocate the bits */
+ bits = HeapAlloc(GetProcessHeap(), 0, ShortcutBitmapInfo.bmHeight*ShortcutBitmapInfo.bmWidthBytes);
+ if(!bits) goto fail;
+
+ ZeroMemory(buffer, sizeof(buffer));
+ lpbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ lpbmi->bmiHeader.biWidth = ShortcutBitmapInfo.bmWidth;
+ lpbmi->bmiHeader.biHeight = ShortcutBitmapInfo.bmHeight;
+ lpbmi->bmiHeader.biPlanes = 1;
+ lpbmi->bmiHeader.biBitCount = 32;
+
+ if(!GetDIBits(TargetDC, ShortcutIconInfo.hbmColor, 0, ShortcutBitmapInfo.bmHeight, bits, lpbmi, DIB_RGB_COLORS))
+ {
+ ERR("GetBIBits failed!\n");
+ HeapFree(GetProcessHeap(), 0, bits);
+ goto fail;
+ }
+
+ pixel = (PULONG)bits;
+ /* Remove alpha channel component or make it totally opaque */
+ for(i=0; i<ShortcutBitmapInfo.bmHeight; i++)
+ {
+ for(j=0; j<ShortcutBitmapInfo.bmWidth; j++)
+ {
+ if(add_alpha) *pixel++ |= 0xFF000000;
+ else *pixel++ &= 0x00FFFFFF;
+ }
+ }
+
+ /* GetDIBits return BI_BITFIELDS with masks set to 0, and SetDIBits fails when masks are 0. The irony... */
+ lpbmi->bmiHeader.biCompression = BI_RGB;
+
+ /* Set the bits again */
+ if(!SetDIBits(TargetDC, ShortcutIconInfo.hbmColor, 0, ShortcutBitmapInfo.bmHeight, bits, lpbmi, DIB_RGB_COLORS))
+ {
+ ERR("SetBIBits failed!, %lu\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, bits);
+ goto fail;
+ }
+ HeapFree(GetProcessHeap(), 0, bits);
}
- /* 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,
+ /* Now do the copy. We overwrite the original icon data */
+ if (NULL == SelectObject(ShortcutDC, ShortcutIconInfo.hbmColor) ||
+ NULL == SelectObject(TargetDC, TargetIconInfo.hbmColor))
+ goto fail;
+ if (!MaskBlt(TargetDC, 0, 0, ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
ShortcutDC, 0, 0, ShortcutIconInfo.hbmMask, 0, 0,
MAKEROP4(0xAA0000, SRCCOPY)))
{
/* 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);
/* 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;
}
* 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);
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);
+ 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)
- {
+ if (index!=index1)
+ {
FIXME("iconlists out of sync 0x%x 0x%x\n", index, index1);
- }
- lpsice->dwListIndex = index;
- ret = lpsice->dwListIndex;
+ /* 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;
}
* 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);
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]
LeaveCriticalSection(&SHELL32_SicCS);
return ret;
}
+
/*****************************************************************************
* SIC_Initialize [internal]
*/
HDC hDC;
INT bpp;
DWORD ilMask;
+ BOOL result = FALSE;
TRACE("Entered SIC_Initialize\n");
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;
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)
- {
- /* 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;
- }
+ if (!ShellBigIconList)
+ {
+ 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;
- }
+ ERR("Failed to load large IDI_SHELL_DOCUMENT icon!\n");
+ goto end;
}
- else
+
+ if(SIC_IconAppend(swShell32Name, IDI_SHELL_DOCUMENT-1, hSm, hLg, 0) == INVALID_INDEX)
{
- ERR("Failed to load ShellBigIconList\n");
- return FALSE;
+ 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;
}
-
- SIC_IconAppend(swShell32Name, IDI_SHELL_DOCUMENT-1, hSm, hLg, 0);
- SIC_IconAppend(swShell32Name, -IDI_SHELL_DOCUMENT, hSm, hLg, 0);
TRACE("hIconSmall=%p hIconBig=%p\n",ShellSmallIconList, ShellBigIconList);
- return TRUE;
+ return result;
}
+
/*************************************************************************
* SIC_Destroy
*
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
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 (
OUT PLONG LastY)
{
NTSTATUS Status;
+ ULONG ValueX, ValueY;
/* init result */
*LastX = 0;
/* 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(
TempList = DeviceExtension->CurrentUsageList;
DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList;
DeviceExtension->PreviousUsageList = TempList;
+
+ if (DeviceExtension->MouseAbsolute)
+ {
+ // mouse operates absolute
+ *ButtonFlags |= MOUSE_MOVE_ABSOLUTE;
+ }
}
VOID
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));
}
}
+ 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 */
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;
//
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
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);
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;
//
UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension;
+ // get hub device extension
+ HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbChildExtension->ParentDeviceObject->DeviceExtension;
+
//
// get device descriptor
//
//
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))
{
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)
{
}
HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] = NewChildDeviceObject;
+ HubDeviceExtension->InstanceCount++;
IoInvalidateDeviceRelations(RootHubDeviceObject, BusRelations);
return STATUS_SUCCESS;
ULONG Index;
ULONG bFound;
PDEVICE_RELATIONS DeviceRelation;
+ PDEVICE_OBJECT ParentDevice;
UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
{
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");
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;
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);
PVOID RootHubHandle;
USB_BUS_INTERFACE_USBDI_V2 DeviceInterface;
-
UNICODE_STRING SymbolicLinkName;
+ ULONG InstanceCount;
+
} HUB_DEVICE_EXTENSION, *PHUB_DEVICE_EXTENSION;
// createclose.c
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);
//
// create pdo
//
- Status = USBSTOR_CreatePDO(DeviceObject, Index, &DeviceExtension->ChildPDO[Index]);
+ Status = USBSTOR_CreatePDO(DeviceObject, Index);
//
// check for failure
// increment pdo index
//
Index++;
+ DeviceExtension->InstanceCount++;
}while(Index < DeviceExtension->MaxLUN);
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;
}
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);
}
//
// 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;
Status = STATUS_SUCCESS;
break;
}
+ case IRP_MN_SURPRISE_REMOVAL:
+ {
+ Status = STATUS_SUCCESS;
+ break;
+ }
default:
{
//
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
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;
//
// output device object
//
- *ChildDeviceObject = PDO;
+ FDODeviceExtension->ChildPDO[LUN] = PDO;
//
// send inquiry command by irp
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
NTSTATUS
USBSTOR_CreatePDO(
IN PDEVICE_OBJECT DeviceObject,
- IN UCHAR LUN,
- OUT PDEVICE_OBJECT *ChildDeviceObject);
+ IN UCHAR LUN);
//---------------------------------------------------------------------
//
GroupReplicationInformation
} GROUP_INFORMATION_CLASS;
+typedef struct _GROUP_MEMBERSHIP
+{
+ ULONG RelativeId;
+ ULONG Attributes;
+} GROUP_MEMBERSHIP, *PGROUP_MEMBERSHIP;
+
typedef enum _USER_INFORMATION_CLASS
{
UserGeneralInformation = 1,
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);
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,
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,
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,
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);
[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
{
#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))
#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
}
+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(
//
// 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
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;
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
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
OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes,
IN OUT PULONG LinkCollectionNodesLength);
+
HIDAPI
NTSTATUS
NTAPI
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
IN PDEVICE_OBJECT DeviceObject
);
+VOID
+NTAPI
+PoRemoveVolumeDevice(
+ IN PDEVICE_OBJECT DeviceObject);
+
//
// Power State routines
//
/* 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);
}
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)
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;
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)
{
}
}
+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)
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);
}
/**
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)
*/
#include <win32k.h>
-
-#define NDEBUG
-#include <debug.h>
+DBG_DEFAULT_CHANNEL(GdiBlt);
#define ROP_USES_SOURCE(Rop) (((((Rop) & 0xCC0000) >> 2) != ((Rop) & 0x330000)) || ((((Rop) & 0xCC000000) >> 2) != ((Rop) & 0x33000000)))
#define ROP_USES_MASK(Rop) (((Rop) & 0xFF000000) != (((Rop) & 0xff0000) << 8))
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;
}
}
/* 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 */
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,
EXLATEOBJ_vCleanup(&exlo);
leave :
- DPRINT("Finishing blit\n");
+ TRACE("Finishing blit\n");
DC_vFinishBlit(DCDest, DCSrc);
GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
GDIOBJ_vUnlockObject(&DCDest->BaseObject);
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;
}
}
else if(psurfMask)
{
- DPRINT1("Getting Mask bitmap without needing it?\n");
+ WARN("Getting Mask bitmap without needing it?\n");
SURFACE_ShareUnlockSurface(psurfMask);
psurfMask = NULL;
}
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;
}
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;
}
IN INT yMask,
IN DWORD crBackColor)
{
- UNIMPLEMENTED;
+ FIXME("NtGdiPlgBlt: unimplemented.\n");
return FALSE;
}
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;
}
(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);
if (pbrush != NULL)
{
/* Initialize a brush object */
- EBRUSHOBJ_vInit(&eboFill, pbrush, pdc);
+ EBRUSHOBJ_vInitFromDC(&eboFill, pbrush, pdc);
IntPatBlt(
pdc,
extern HSURF gahsurfHatch[HS_DDI_MAX];
+struct _SURFACE;
+struct _PALETTE;
struct _DC;
INIT_FUNCTION
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
VOID
NTAPI
-EBRUSHOBJ_vUpdate(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _DC *pdc);
+EBRUSHOBJ_vUpdateFromDC(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _DC *);
BOOL
NTAPI
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;
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 */
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 */
/* 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);
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);
}
#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,
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)
{
- return FALSE;
+ /* 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;
}
-
- if(!(hMemDC = NtGdiCreateCompatibleDC(hDc)))
+ else if ((psurfColor = SURFACE_ShareLockSurface(hbmColor)) == NULL)
{
- ERR("NtGdiCreateCompatibleDC failed!\n");
+ ERR("Unable to lock the color bitmap.\n");
+ SURFACE_ShareUnlockSurface(psurfMask);
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(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)
- cyHeight = ((diFlags & DI_DEFAULTSIZE) ?
- UserGetSystemMetrics(SM_CYICON) : pIcon->Size.cy);
+ {
+ if(diFlags & DI_DEFAULTSIZE)
+ cyHeight = pIcon->IconInfo.fIcon ?
+ UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR);
+ else
+ cyHeight = pIcon->Size.cy;
+ }
- DoFlickerFree = (hbrFlickerFreeDraw &&
- (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH));
+ /* Should we render off-screen? */
+ bOffScreen = hbrFlickerFreeDraw && (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH);
- if (DoFlickerFree)
+ if (bOffScreen)
{
- hDestDC = NtGdiCreateCompatibleDC(hDc);
- if(!hDestDC)
+ /* 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("NtGdiCreateCompatibleDC failed!\n");
- Ret = FALSE;
- goto Cleanup ;
+ ERR("Failed to allocate the off-screen surface.\n");
+ SURFACE_ShareUnlockSurface(psurfMask);
+ if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
+ BRUSH_ShareUnlockBrush(pbrush);
+ return FALSE;
}
- hOffBmp = NtGdiCreateCompatibleBitmap(hDc, cxWidth, cyHeight);
- if(!hOffBmp)
+
+ /* 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("NtGdiCreateCompatibleBitmap failed!\n");
- goto Cleanup ;
+ 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;
}
- hOldOffBmp = NtGdiSelectBitmap(hDestDC, hOffBmp);
- hOldOffBrush = NtGdiSelectBrush(hDestDC, hbrFlickerFreeDraw);
- NtGdiPatBlt(hDestDC, 0, 0, cxWidth, cyHeight, PATCOPY);
- NtGdiSelectBrush(hDestDC, hOldOffBrush);
- x=y=0;
}
- /* Set Background/foreground colors */
- iOldTxtColor = IntGdiSetTextColor(hDc, 0); // Black
- iOldBkColor = IntGdiSetBkColor(hDc, 0x00FFFFFF); // White
-
+ /* 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");
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(hOldOffBmp) NtGdiSelectBitmap(hDestDC, hOldOffBmp);
- NtGdiDeleteObjectApp(hDestDC);
- if(hOffBmp) NtGdiDeleteObjectApp(hOffBmp);
- }
+ if(pdc)
+ {
+ 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;
}