Synchronize with trunk's revision r57599.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 23 Oct 2012 19:54:03 +0000 (19:54 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 23 Oct 2012 19:54:03 +0000 (19:54 +0000)
svn path=/branches/ros-csrss/; revision=57600

36 files changed:
boot/bootdata/hivesys_amd64.inf
boot/bootdata/hivesys_arm.inf
boot/bootdata/hivesys_i386.inf
dll/win32/lsasrv/CMakeLists.txt
dll/win32/lsasrv/lookup.c [moved from dll/win32/lsasrv/sids.c with 89% similarity]
dll/win32/lsasrv/lsasrv.h
dll/win32/samlib/samlib.c
dll/win32/samlib/samlib.spec
dll/win32/shell32/iconcache.cpp
drivers/hid/hidparse/hidparse.c
drivers/hid/mouhid/mouhid.c
drivers/hid/mouhid/mouhid.h
drivers/usb/usbd/usbd.c
drivers/usb/usbhub/fdo.c
drivers/usb/usbhub/pdo.c
drivers/usb/usbhub/usbhub.h
drivers/usb/usbstor/fdo.c
drivers/usb/usbstor/pdo.c
drivers/usb/usbstor/usbstor.h
include/ddk/ntsam.h
include/reactos/idl/sam.idl
include/reactos/wine/unicode.h
lib/drivers/hidparser/api.c
lib/drivers/hidparser/hidparser.c
lib/drivers/hidparser/hidparser.h
lib/drivers/hidparser/parser.h
ntoskrnl/include/internal/po.h
ntoskrnl/io/iomgr/device.c
ntoskrnl/po/povolume.c
win32ss/gdi/eng/engbrush.c
win32ss/gdi/eng/xlateobj.c
win32ss/gdi/ntgdi/bitblt.c
win32ss/gdi/ntgdi/brush.h
win32ss/gdi/ntgdi/dclife.c
win32ss/gdi/ntgdi/dcobjs.c
win32ss/user/ntuser/cursoricon.c

index 2149d3b..f3cc661 100644 (file)
@@ -1221,6 +1221,7 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olecli32",0x0
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olesvr32",0x00000000,"olesvr32.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olethk32",0x00000000,"olethk32.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","rpcrt4",0x00000000,"rpcrt4.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","setupapi",0x00000000,"setupapi.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","shell32",0x00000000,"shell32.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","url",0x00000000,"url.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","urlmon",0x00000000,"urlmon.dll"
index cec534f..3fe7986 100644 (file)
@@ -776,6 +776,7 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olecli32",0x0
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olesvr32",0x00000000,"olesvr32.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olethk32",0x00000000,"olethk32.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","rpcrt4",0x00000000,"rpcrt4.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","setupapi",0x00000000,"setupapi.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","shell32",0x00000000,"shell32.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","url",0x00000000,"url.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","urlmon",0x00000000,"urlmon.dll"
index 2149d3b..f3cc661 100644 (file)
@@ -1221,6 +1221,7 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olecli32",0x0
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olesvr32",0x00000000,"olesvr32.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olethk32",0x00000000,"olethk32.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","rpcrt4",0x00000000,"rpcrt4.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","setupapi",0x00000000,"setupapi.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","shell32",0x00000000,"shell32.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","url",0x00000000,"url.dll"
 HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","urlmon",0x00000000,"urlmon.dll"
index 90c7b5e..28d5533 100644 (file)
@@ -13,11 +13,11 @@ spec2def(lsasrv.dll lsasrv.spec ADD_IMPORTLIB)
 list(APPEND SOURCE
     authport.c
     database.c
+    lookup.c
     lsarpc.c
     lsasrv.c
     policy.c
     privileges.c
-    sids.c
     lsasrv.rc
     ${CMAKE_CURRENT_BINARY_DIR}/lsasrv_stubs.c
     ${CMAKE_CURRENT_BINARY_DIR}/lsasrv.def
similarity index 89%
rename from dll/win32/lsasrv/sids.c
rename to dll/win32/lsasrv/lookup.c
index b363970..3cc4973 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         Local Security Authority (LSA) Server
- * FILE:            reactos/dll/win32/lsasrv/sids.c
+ * FILE:            reactos/dll/win32/lsasrv/lookup.c
  * PURPOSE:         Sid / Name lookup functions
  *
  * PROGRAMMERS:     Eric Kohl
@@ -72,8 +72,8 @@ typedef struct _WELL_KNOWN_SID
 {
     LIST_ENTRY ListEntry;
     PSID Sid;
-    UNICODE_STRING Name;
-    UNICODE_STRING Domain;
+    UNICODE_STRING AccountName;
+    UNICODE_STRING DomainName;
     SID_NAME_USE Use;
 } WELL_KNOWN_SID, *PWELL_KNOWN_SID;
 
@@ -202,8 +202,8 @@ BOOLEAN
 LsapCreateSid(PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
               UCHAR SubAuthorityCount,
               PULONG SubAuthorities,
-              PWSTR Name,
-              PWSTR Domain,
+              PWSTR AccountName,
+              PWSTR DomainName,
               SID_NAME_USE Use)
 {
     PWELL_KNOWN_SID SidEntry;
@@ -235,11 +235,11 @@ LsapCreateSid(PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
         *p = SubAuthorities[i];
     }
 
-    RtlInitUnicodeString(&SidEntry->Name,
-                         Name);
+    RtlInitUnicodeString(&SidEntry->AccountName,
+                         AccountName);
 
-    RtlInitUnicodeString(&SidEntry->Domain,
-                         Domain);
+    RtlInitUnicodeString(&SidEntry->DomainName,
+                         DomainName);
 
     SidEntry->Use = Use;
 
@@ -472,6 +472,13 @@ LsapInitSids(VOID)
                   L"NT AUTHORITY",
                   SidTypeWellKnownGroup);
 
+    LsapCreateSid(&NtAuthority,
+                  1,
+                  SubAuthorities,
+                  L"LOCALSERVICE",
+                  L"NT AUTHORITY",
+                  SidTypeWellKnownGroup);
+
     /* Network Service Sid */
     SubAuthorities[0] = SECURITY_NETWORK_SERVICE_RID;
     LsapCreateSid(&NtAuthority,
@@ -481,6 +488,13 @@ LsapInitSids(VOID)
                   L"NT AUTHORITY",
                   SidTypeWellKnownGroup);
 
+    LsapCreateSid(&NtAuthority,
+                  1,
+                  SubAuthorities,
+                  L"NETWORKSERVICE",
+                  L"NT AUTHORITY",
+                  SidTypeWellKnownGroup);
+
     /* Builtin Domain Sid */
     SubAuthorities[0] = SECURITY_BUILTIN_DOMAIN_RID;
     LsapCreateSid(&NtAuthority,
@@ -653,7 +667,32 @@ LsapLookupWellKnownSid(PSID Sid)
 
 
 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;
@@ -664,7 +703,8 @@ LsapLookupWellKnownName(PUNICODE_STRING Name)
         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;
         }
@@ -975,6 +1015,37 @@ CreateDomainSidFromAccountSid(PSID AccountSid)
 }
 
 
+static PSID
+LsapCopySid(PSID SrcSid)
+{
+    UCHAR RidCount;
+    PSID DstSid;
+    ULONG i;
+    ULONG DstSidSize;
+    PULONG p, q;
+
+    RidCount = *RtlSubAuthorityCountSid(SrcSid);
+    DstSidSize = RtlLengthRequiredSid(RidCount);
+
+    DstSid = MIDL_user_allocate(DstSidSize);
+    if (DstSid == NULL)
+        return NULL;
+
+    RtlInitializeSid(DstSid,
+                     RtlIdentifierAuthoritySid(SrcSid),
+                     RidCount);
+
+    for (i = 0; i < (ULONG)RidCount; i++)
+    {
+        p = RtlSubAuthoritySid(SrcSid, i);
+        q = RtlSubAuthoritySid(DstSid, i);
+        *q = *p;
+    }
+
+    return DstSid;
+}
+
+
 static
 NTSTATUS
 LsapLookupIsolatedNames(DWORD Count,
@@ -1004,18 +1075,24 @@ LsapLookupIsolatedNames(DWORD Count,
         TRACE("Mapping name: %wZ\n", &AccountNames[i]);
 
         /* Look-up all well-known names */
-        ptr = LsapLookupWellKnownName((PUNICODE_STRING)&AccountNames[i]);
+        ptr = LsapLookupIsolatedWellKnownName((PUNICODE_STRING)&AccountNames[i]);
         if (ptr != NULL)
         {
             SidsBuffer[i].Use = ptr->Use;
-            SidsBuffer[i].Sid = ptr->Sid;
+            SidsBuffer[i].Sid = LsapCopySid(ptr->Sid);
+            if (SidsBuffer[i].Sid == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                goto done;
+            }
+
             SidsBuffer[i].DomainIndex = -1;
             SidsBuffer[i].Flags = 0;
 
             if (ptr->Use == SidTypeDomain)
             {
                 Status = LsapAddDomainToDomainsList(DomainsBuffer,
-                                                    &ptr->Name,
+                                                    &ptr->AccountName,
                                                     ptr->Sid,
                                                     &DomainIndex);
                 if (!NT_SUCCESS(Status))
@@ -1025,11 +1102,11 @@ LsapLookupIsolatedNames(DWORD Count,
             }
             else
             {
-                ptr2= LsapLookupWellKnownName(&ptr->Domain);
+                ptr2= LsapLookupIsolatedWellKnownName(&ptr->DomainName);
                 if (ptr2 != NULL)
                 {
                     Status = LsapAddDomainToDomainsList(DomainsBuffer,
-                                                        &ptr2->Name,
+                                                        &ptr2->AccountName,
                                                         ptr2->Sid,
                                                         &DomainIndex);
                     if (!NT_SUCCESS(Status))
@@ -1072,7 +1149,13 @@ LsapLookupIsolatedNames(DWORD Count,
         if (RtlEqualUnicodeString((PUNICODE_STRING)&AccountNames[i], &BuiltinDomainName, TRUE))
         {
             SidsBuffer[i].Use = SidTypeDomain;
-            SidsBuffer[i].Sid = BuiltinDomainSid;
+            SidsBuffer[i].Sid = LsapCopySid(BuiltinDomainSid);
+            if (SidsBuffer[i].Sid == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                goto done;
+            }
+
             SidsBuffer[i].DomainIndex = -1;
             SidsBuffer[i].Flags = 0;
 
@@ -1093,7 +1176,12 @@ LsapLookupIsolatedNames(DWORD Count,
         if (RtlEqualUnicodeString((PUNICODE_STRING)&AccountNames[i], &AccountDomainName, TRUE))
         {
             SidsBuffer[i].Use = SidTypeDomain;
-            SidsBuffer[i].Sid = AccountDomainSid;
+            SidsBuffer[i].Sid = LsapCopySid(AccountDomainSid);
+            if (SidsBuffer[i].Sid == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                goto done;
+            }
             SidsBuffer[i].DomainIndex = -1;
             SidsBuffer[i].Flags = 0;
 
@@ -1183,7 +1271,10 @@ LsapLookupIsolatedBuiltinNames(DWORD Count,
             SidsBuffer[i].Sid = CreateSidFromSidAndRid(BuiltinDomainSid,
                                                        RelativeIds.Element[0]);
             if (SidsBuffer[i].Sid == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
                 goto done;
+            }
 
             SidsBuffer[i].DomainIndex = -1;
             SidsBuffer[i].Flags = 0;
@@ -1278,7 +1369,10 @@ LsapLookupIsolatedAccountNames(DWORD Count,
             SidsBuffer[i].Sid = CreateSidFromSidAndRid(AccountDomainSid,
                                                        RelativeIds.Element[0]);
             if (SidsBuffer[i].Sid == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
                 goto done;
+            }
 
             SidsBuffer[i].DomainIndex = -1;
             SidsBuffer[i].Flags = 0;
@@ -1310,6 +1404,114 @@ done:
 }
 
 
+static
+NTSTATUS
+LsapLookupFullyQualifiedWellKnownNames(DWORD Count,
+                                       PRPC_UNICODE_STRING DomainNames,
+                                       PRPC_UNICODE_STRING AccountNames,
+                                       PLSAPR_REFERENCED_DOMAIN_LIST DomainsBuffer,
+                                       PLSAPR_TRANSLATED_SID_EX2 SidsBuffer,
+                                       PULONG Mapped)
+{
+    UNICODE_STRING EmptyDomainName = RTL_CONSTANT_STRING(L"");
+    PWELL_KNOWN_SID ptr, ptr2;
+    PSID DomainSid;
+    ULONG DomainIndex;
+    ULONG i;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    for (i = 0; i < Count; i++)
+    {
+        /* Ignore names which were already mapped */
+        if (SidsBuffer[i].Use != SidTypeUnknown)
+            continue;
+
+        /* Ignore isolated account names */
+        if (DomainNames[i].Length == 0)
+            continue;
+
+        TRACE("Mapping name: %wZ\\%wZ\n", &DomainNames[i], &AccountNames[i]);
+
+        /* Look-up all well-known names */
+        ptr = LsapLookupFullyQualifiedWellKnownName((PUNICODE_STRING)&AccountNames[i],
+                                                    (PUNICODE_STRING)&DomainNames[i]);
+        if (ptr != NULL)
+        {
+            TRACE("Found it! (%wZ\\%wZ)\n", &ptr->DomainName, &ptr->AccountName);
+
+            SidsBuffer[i].Use = ptr->Use;
+            SidsBuffer[i].Sid = LsapCopySid(ptr->Sid);
+            if (SidsBuffer[i].Sid == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                goto done;
+            }
+
+            SidsBuffer[i].DomainIndex = -1;
+            SidsBuffer[i].Flags = 0;
+
+            if (ptr->Use == SidTypeDomain)
+            {
+                Status = LsapAddDomainToDomainsList(DomainsBuffer,
+                                                    &ptr->AccountName,
+                                                    ptr->Sid,
+                                                    &DomainIndex);
+                if (!NT_SUCCESS(Status))
+                    goto done;
+
+                SidsBuffer[i].DomainIndex = DomainIndex;
+            }
+            else
+            {
+                ptr2= LsapLookupIsolatedWellKnownName(&ptr->DomainName);
+                if (ptr2 != NULL)
+                {
+                    Status = LsapAddDomainToDomainsList(DomainsBuffer,
+                                                        &ptr2->AccountName,
+                                                        ptr2->Sid,
+                                                        &DomainIndex);
+                    if (!NT_SUCCESS(Status))
+                        goto done;
+
+                    SidsBuffer[i].DomainIndex = DomainIndex;
+                }
+                else
+                {
+                    DomainSid = CreateDomainSidFromAccountSid(ptr->Sid);
+                    if (DomainSid == NULL)
+                    {
+                        Status = STATUS_INSUFFICIENT_RESOURCES;
+                        goto done;
+                    }
+
+                    Status = LsapAddDomainToDomainsList(DomainsBuffer,
+                                                        &EmptyDomainName,
+                                                        DomainSid,
+                                                        &DomainIndex);
+
+                    if (DomainSid != NULL)
+                    {
+                        MIDL_user_free(DomainSid);
+                        DomainSid = NULL;
+                    }
+
+                    if (!NT_SUCCESS(Status))
+                        goto done;
+
+                    SidsBuffer[i].DomainIndex = DomainIndex;
+                }
+            }
+
+            (*Mapped)++;
+            continue;
+        }
+    }
+
+done:
+    return Status;
+}
+
+
 static
 NTSTATUS
 LsapLookupBuiltinNames(DWORD Count,
@@ -1359,6 +1561,8 @@ LsapLookupBuiltinNames(DWORD Count,
         if (!RtlEqualUnicodeString((PUNICODE_STRING)&DomainNames[i], &BuiltinDomainName, TRUE))
             continue;
 
+        TRACE("Mapping name: %wZ\\%wZ\n", &DomainNames[i], &AccountNames[i]);
+
         Status = SamrLookupNamesInDomain(DomainHandle,
                                          1,
                                          &AccountNames[i],
@@ -1370,7 +1574,10 @@ LsapLookupBuiltinNames(DWORD Count,
             SidsBuffer[i].Sid = CreateSidFromSidAndRid(BuiltinDomainSid,
                                                        RelativeIds.Element[0]);
             if (SidsBuffer[i].Sid == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
                 goto done;
+            }
 
             SidsBuffer[i].DomainIndex = -1;
             SidsBuffer[i].Flags = 0;
@@ -1451,6 +1658,8 @@ LsapLookupAccountNames(DWORD Count,
         if (!RtlEqualUnicodeString((PUNICODE_STRING)&DomainNames[i], &AccountDomainName, TRUE))
             continue;
 
+        TRACE("Mapping name: %wZ\\%wZ\n", &DomainNames[i], &AccountNames[i]);
+
         Status = SamrLookupNamesInDomain(DomainHandle,
                                          1,
                                          &AccountNames[i],
@@ -1462,7 +1671,10 @@ LsapLookupAccountNames(DWORD Count,
             SidsBuffer[i].Sid = CreateSidFromSidAndRid(AccountDomainSid,
                                                        RelativeIds.Element[0]);
             if (SidsBuffer[i].Sid == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
                 goto done;
+            }
 
             SidsBuffer[i].DomainIndex = -1;
             SidsBuffer[i].Flags = 0;
@@ -1509,13 +1721,10 @@ LsapLookupNames(DWORD Count,
     PRPC_UNICODE_STRING DomainNames = NULL;
     PRPC_UNICODE_STRING AccountNames = NULL;
     ULONG SidsBufferLength;
-//    ULONG DomainIndex;
     ULONG i;
     ULONG Mapped = 0;
     NTSTATUS Status = STATUS_SUCCESS;
 
-//    PWELL_KNOWN_SID ptr, ptr2;
-
 //TRACE("()\n");
 
     TranslatedSids->Entries = 0;
@@ -1621,7 +1830,22 @@ LsapLookupNames(DWORD Count,
     if (Mapped == Count)
         goto done;
 
+    Status = LsapLookupFullyQualifiedWellKnownNames(Count,
+                                                    DomainNames,
+                                                    AccountNames,
+                                                    DomainsBuffer,
+                                                    SidsBuffer,
+                                                    &Mapped);
+    if (!NT_SUCCESS(Status) &&
+        Status != STATUS_NONE_MAPPED &&
+        Status != STATUS_SOME_NOT_MAPPED)
+    {
+        TRACE("LsapLookupFullyQualifiedWellKnownNames failed! (Status %lx)\n", Status);
+        goto done;
+    }
 
+    if (Mapped == Count)
+        goto done;
 
     Status = LsapLookupBuiltinNames(Count,
                                     DomainNames,
@@ -1755,16 +1979,22 @@ LsapLookupWellKnownSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
             NamesBuffer[i].Use = ptr->Use;
             NamesBuffer[i].Flags = 0;
 
-            NamesBuffer[i].Name.Buffer = MIDL_user_allocate(ptr->Name.MaximumLength);
-            NamesBuffer[i].Name.Length = ptr->Name.Length;
-            NamesBuffer[i].Name.MaximumLength = ptr->Name.MaximumLength;
-            RtlCopyMemory(NamesBuffer[i].Name.Buffer, ptr->Name.Buffer, ptr->Name.MaximumLength);
+            NamesBuffer[i].Name.Length = ptr->AccountName.Length;
+            NamesBuffer[i].Name.MaximumLength = ptr->AccountName.MaximumLength;
+            NamesBuffer[i].Name.Buffer = MIDL_user_allocate(ptr->AccountName.MaximumLength);
+            if (NamesBuffer[i].Name.Buffer == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                goto done;
+            }
+
+            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))
@@ -2062,82 +2292,6 @@ done:
 }
 
 
-static NTSTATUS
-LsapLookupUnknownSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
-                      PLSAPR_TRANSLATED_NAME_EX NamesBuffer,
-                      PLSAPR_REFERENCED_DOMAIN_LIST DomainsBuffer,
-                      PULONG Mapped)
-{
-    SID_IDENTIFIER_AUTHORITY IdentifierAuthority = {SECURITY_NT_AUTHORITY};
-    static const UNICODE_STRING DomainName = RTL_CONSTANT_STRING(L"UNKNOWN");
-    static const UNICODE_STRING AdminName = RTL_CONSTANT_STRING(L"Test");
-    PSID AdminsSid = NULL;
-    LPWSTR SidString = NULL;
-    ULONG SidLength;
-    ULONG DomainIndex;
-    ULONG i;
-    NTSTATUS Status;
-
-    Status = RtlAllocateAndInitializeSid(&IdentifierAuthority,
-                                         2,
-                                         SECURITY_BUILTIN_DOMAIN_RID,
-                                         DOMAIN_ALIAS_RID_ADMINS,
-                                         0, 0, 0, 0, 0, 0,
-                                         &AdminsSid);
-    if (!NT_SUCCESS(Status))
-        goto done;
-
-    SidLength = RtlLengthSid(AdminsSid);
-
-    for (i = 0; i < SidEnumBuffer->Entries; i++)
-    {
-        /* Ignore SIDs which are already mapped */
-        if (NamesBuffer[i].Use != SidTypeUnknown)
-            continue;
-
-
-        ConvertSidToStringSidW(SidEnumBuffer->SidInfo[i].Sid, &SidString);
-        TRACE("Mapping SID: %S\n", SidString);
-        LocalFree(SidString);
-        SidString = NULL;
-
-
-        /* Hack: Map the SID to the Admin Account if it is not a well-known SID */
-        NamesBuffer[i].Use = SidTypeUser;
-        NamesBuffer[i].Flags = 0;
-        NamesBuffer[i].Name.Length = AdminName.Length;
-        NamesBuffer[i].Name.MaximumLength = AdminName.MaximumLength;
-        NamesBuffer[i].Name.Buffer = MIDL_user_allocate(AdminName.MaximumLength);
-        if (NamesBuffer[i].Name.Buffer == NULL)
-        {
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            goto done;
-        }
-
-        RtlCopyMemory(NamesBuffer[i].Name.Buffer, AdminName.Buffer, AdminName.MaximumLength);
-
-        Status = LsapAddDomainToDomainsList(DomainsBuffer,
-                                            (PUNICODE_STRING)&DomainName,
-                                            AdminsSid,
-                                            &DomainIndex);
-        if (!NT_SUCCESS(Status))
-            goto done;
-
-        NamesBuffer[i].DomainIndex = DomainIndex;
-
-        TRACE("Mapped to: %wZ\n", &NamesBuffer[i].Name);
-
-        (*Mapped)++;
-    }
-
-done:
-    if (AdminsSid != NULL)
-        RtlFreeSid(AdminsSid);
-
-    return Status;
-}
-
-
 NTSTATUS
 LsapLookupSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
                PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains,
@@ -2229,16 +2383,6 @@ LsapLookupSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
     if (Mapped == SidEnumBuffer->Entries)
         goto done;
 
-    /* Map unknown SIDs */
-    Status = LsapLookupUnknownSids(SidEnumBuffer,
-                                   NamesBuffer,
-                                   DomainsBuffer,
-                                   &Mapped);
-    if (!NT_SUCCESS(Status) &&
-        Status != STATUS_NONE_MAPPED &&
-        Status != STATUS_SOME_NOT_MAPPED)
-        goto done;
-
 done:
     TRACE("done Status: %lx  Mapped: %lu\n", Status, Mapped);
 
index 720df26..5f18e5a 100644 (file)
@@ -118,6 +118,32 @@ LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject,
                        LPVOID AttributeData,
                        ULONG AttributeSize);
 
+/* lookup.c */
+NTSTATUS
+LsapInitSids(VOID);
+
+ULONG
+LsapGetRelativeIdFromSid(PSID Sid);
+
+NTSTATUS
+LsapLookupNames(DWORD Count,
+                PRPC_UNICODE_STRING Names,
+                PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains,
+                PLSAPR_TRANSLATED_SIDS_EX2 TranslatedSids,
+                LSAP_LOOKUP_LEVEL LookupLevel,
+                DWORD *MappedCount,
+                DWORD LookupOptions,
+                DWORD ClientRevision);
+
+NTSTATUS
+LsapLookupSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
+               PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains,
+               PLSAPR_TRANSLATED_NAMES_EX TranslatedNames,
+               LSAP_LOOKUP_LEVEL LookupLevel,
+               DWORD *MappedCount,
+               DWORD LookupOptions,
+               DWORD ClientRevision);
+
 /* lsarpc.c */
 VOID
 LsarStartRpcServer(VOID);
@@ -201,30 +227,4 @@ LsarpEnumeratePrivileges(DWORD *EnumerationContext,
                          PLSAPR_PRIVILEGE_ENUM_BUFFER EnumerationBuffer,
                          DWORD PreferedMaximumLength);
 
-/* sids.h */
-NTSTATUS
-LsapInitSids(VOID);
-
-ULONG
-LsapGetRelativeIdFromSid(PSID Sid);
-
-NTSTATUS
-LsapLookupNames(DWORD Count,
-                PRPC_UNICODE_STRING Names,
-                PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains,
-                PLSAPR_TRANSLATED_SIDS_EX2 TranslatedSids,
-                LSAP_LOOKUP_LEVEL LookupLevel,
-                DWORD *MappedCount,
-                DWORD LookupOptions,
-                DWORD ClientRevision);
-
-NTSTATUS
-LsapLookupSids(PLSAPR_SID_ENUM_BUFFER SidEnumBuffer,
-               PLSAPR_REFERENCED_DOMAIN_LIST *ReferencedDomains,
-               PLSAPR_TRANSLATED_NAMES_EX TranslatedNames,
-               LSAP_LOOKUP_LEVEL LookupLevel,
-               DWORD *MappedCount,
-               DWORD LookupOptions,
-               DWORD ClientRevision);
-
 /* EOF */
index 7f07d5a..5607196 100644 (file)
@@ -128,6 +128,66 @@ SamAddMemberToAlias(IN SAM_HANDLE AliasHandle,
 }
 
 
+NTSTATUS
+NTAPI
+SamAddMemberToGroup(IN SAM_HANDLE GroupHandle,
+                    IN ULONG MemberId,
+                    IN ULONG Attributes)
+{
+    NTSTATUS Status;
+
+    TRACE("SamAddMemberToGroup(%p %lu %lx)",
+          GroupHandle, MemberId, Attributes);
+
+    RpcTryExcept
+    {
+        Status = SamrAddMemberToGroup((SAMPR_HANDLE)GroupHandle,
+                                      MemberId,
+                                      Attributes);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+SamAddMultipleMembersToAlias(IN SAM_HANDLE AliasHandle,
+                             IN PSID *MemberIds,
+                             IN ULONG MemberCount)
+{
+    SAMPR_PSID_ARRAY Buffer;
+    NTSTATUS Status;
+
+    TRACE("SamAddMultipleMembersToAlias(%p %p %lu)\n",
+          AliasHandle, MemberIds, MemberCount);
+
+    if (MemberIds == NULL)
+        return STATUS_INVALID_PARAMETER_2;
+
+    Buffer.Count = MemberCount;
+    Buffer.Sids = (PSAMPR_SID_INFORMATION)MemberIds;
+
+    RpcTryExcept
+    {
+        Status = SamrAddMultipleMembersToAlias((SAMPR_HANDLE)AliasHandle,
+                                               &Buffer);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
 NTSTATUS
 NTAPI
 SamCloseHandle(IN SAM_HANDLE SamHandle)
@@ -320,6 +380,90 @@ SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
 }
 
 
+NTSTATUS
+NTAPI
+SamDeleteAlias(IN SAM_HANDLE AliasHandle)
+{
+    SAMPR_HANDLE LocalAliasHandle;
+    NTSTATUS Status;
+
+    TRACE("SamDeleteAlias(%p)\n", AliasHandle);
+
+    LocalAliasHandle = (SAMPR_HANDLE)AliasHandle;
+
+    if (LocalAliasHandle == NULL)
+        return STATUS_INVALID_HANDLE;
+
+    RpcTryExcept
+    {
+        Status = SamrDeleteAlias(&LocalAliasHandle);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+SamDeleteGroup(IN SAM_HANDLE GroupHandle)
+{
+    SAMPR_HANDLE LocalGroupHandle;
+    NTSTATUS Status;
+
+    TRACE("SamDeleteGroup(%p)\n", GroupHandle);
+
+    LocalGroupHandle = (SAMPR_HANDLE)GroupHandle;
+
+    if (LocalGroupHandle == NULL)
+        return STATUS_INVALID_HANDLE;
+
+    RpcTryExcept
+    {
+        Status = SamrDeleteGroup(&LocalGroupHandle);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+SamDeleteUser(IN SAM_HANDLE UserHandle)
+{
+    SAMPR_HANDLE LocalUserHandle;
+    NTSTATUS Status;
+
+    TRACE("SamDeleteUser(%p)\n", UserHandle);
+
+    LocalUserHandle = (SAMPR_HANDLE)UserHandle;
+
+    if (LocalUserHandle == NULL)
+        return STATUS_INVALID_HANDLE;
+
+    RpcTryExcept
+    {
+        Status = SamrDeleteUser(&LocalUserHandle);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
 NTSTATUS
 NTAPI
 SamEnumerateAliasesInDomain(IN SAM_HANDLE DomainHandle,
@@ -577,6 +721,50 @@ SamGetAliasMembership(IN SAM_HANDLE DomainHandle,
 }
 
 
+NTSTATUS
+NTAPI
+SamGetGroupsForUser(IN SAM_HANDLE UserHandle,
+                    OUT PGROUP_MEMBERSHIP *Groups,
+                    OUT PULONG MembershipCount)
+{
+    PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL;
+    NTSTATUS Status;
+
+    TRACE("SamGetGroupsForUser(%p %p %p)\n",
+          UserHandle, Groups, MembershipCount);
+
+    RpcTryExcept
+    {
+        Status = SamrGetGroupsForUser((SAMPR_HANDLE)UserHandle,
+                                      &GroupsBuffer);
+        if (NT_SUCCESS(Status))
+        {
+            *Groups = GroupsBuffer->Groups;
+            *MembershipCount = GroupsBuffer->MembershipCount;
+
+            MIDL_user_free(GroupsBuffer);
+        }
+        else
+        {
+            if (GroupsBuffer != NULL)
+            {
+                if (GroupsBuffer->Groups != NULL)
+                    MIDL_user_free(GroupsBuffer->Groups);
+
+                MIDL_user_free(GroupsBuffer);
+            }
+        }
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
 NTSTATUS
 NTAPI
 SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
@@ -619,6 +807,55 @@ SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
 }
 
 
+NTSTATUS
+NTAPI
+SamGetMembersInGroup(IN SAM_HANDLE GroupHandle,
+                     OUT PULONG *MemberIds,
+                     OUT PULONG *Attributes,
+                     OUT PULONG MemberCount)
+{
+    PSAMPR_GET_MEMBERS_BUFFER MembersBuffer = NULL;
+    NTSTATUS Status;
+
+    TRACE("SamGetMembersInGroup(%p %p %p %p)\n",
+          GroupHandle, MemberIds, Attributes, MemberCount);
+
+    RpcTryExcept
+    {
+        Status = SamrGetMembersInGroup((SAMPR_HANDLE)GroupHandle,
+                                       &MembersBuffer);
+        if (NT_SUCCESS(Status))
+        {
+            *MemberIds = MembersBuffer->Members;
+            *Attributes = MembersBuffer->Attributes;
+            *MemberCount = MembersBuffer->MemberCount;
+
+            MIDL_user_free(MembersBuffer);
+        }
+        else
+        {
+            if (MembersBuffer != NULL)
+            {
+                if (MembersBuffer->Members != NULL)
+                    MIDL_user_free(MembersBuffer->Members);
+
+                if (MembersBuffer->Attributes != NULL)
+                    MIDL_user_free(MembersBuffer->Attributes);
+
+                MIDL_user_free(MembersBuffer);
+            }
+        }
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
 NTSTATUS
 NTAPI
 SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
@@ -1057,6 +1294,161 @@ SamQueryInformationUser(IN SAM_HANDLE UserHandle,
 }
 
 
+NTSTATUS
+NTAPI
+SamQuerySecurityObject(IN SAM_HANDLE ObjectHandle,
+                       IN SECURITY_INFORMATION SecurityInformation,
+                       OUT PSECURITY_DESCRIPTOR *SecurityDescriptor)
+{
+    SAMPR_SR_SECURITY_DESCRIPTOR LocalSecurityDescriptor;
+    PSAMPR_SR_SECURITY_DESCRIPTOR pLocalSecurityDescriptor;
+    NTSTATUS Status;
+
+    TRACE("SamQuerySecurityObject(%p %lu %p)\n",
+          ObjectHandle, SecurityInformation, SecurityDescriptor);
+
+    LocalSecurityDescriptor.Length = 0;
+    LocalSecurityDescriptor.SecurityDescriptor = NULL;
+
+    RpcTryExcept
+    {
+        pLocalSecurityDescriptor = &LocalSecurityDescriptor;
+
+        Status = SamrQuerySecurityObject((SAMPR_HANDLE)ObjectHandle,
+                                         SecurityInformation,
+                                         &pLocalSecurityDescriptor);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    *SecurityDescriptor = LocalSecurityDescriptor.SecurityDescriptor;
+
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+SamRemoveMemberFromAlias(IN SAM_HANDLE AliasHandle,
+                         IN PSID MemberId)
+{
+    NTSTATUS Status;
+
+    TRACE("SamRemoveMemberFromAlias(%p %ul)\n",
+          AliasHandle, MemberId);
+
+    RpcTryExcept
+    {
+        Status = SamrRemoveMemberFromAlias((SAMPR_HANDLE)AliasHandle,
+                                           MemberId);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+SamRemoveMemberFromForeignDomain(IN SAM_HANDLE DomainHandle,
+                                 IN PSID MemberId)
+{
+    NTSTATUS Status;
+
+    TRACE("SamRemoveMemberFromForeignDomain(%p %ul)\n",
+          DomainHandle, MemberId);
+
+    RpcTryExcept
+    {
+        Status = SamrRemoveMemberFromForeignDomain((SAMPR_HANDLE)DomainHandle,
+                                                   MemberId);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+SamRemoveMemberFromGroup(IN SAM_HANDLE GroupHandle,
+                         IN ULONG MemberId)
+{
+    NTSTATUS Status;
+
+    TRACE("SamRemoveMemberFromGroup(%p %ul)\n",
+          GroupHandle, MemberId);
+
+    RpcTryExcept
+    {
+        Status = SamrRemoveMemberFromGroup((SAMPR_HANDLE)GroupHandle,
+                                           MemberId);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+SamRemoveMultipleMembersFromAlias(IN SAM_HANDLE AliasHandle,
+                                  IN PSID *MemberIds,
+                                  IN ULONG MemberCount)
+{
+    SAMPR_PSID_ARRAY Buffer;
+    NTSTATUS Status;
+
+    TRACE("SamRemoveMultipleMembersFromAlias(%p %p %lu)\n",
+          AliasHandle, MemberIds, MemberCount);
+
+    if (MemberIds == NULL)
+        return STATUS_INVALID_PARAMETER_2;
+
+    Buffer.Count = MemberCount;
+    Buffer.Sids = (PSAMPR_SID_INFORMATION)MemberIds;
+
+    RpcTryExcept
+    {
+        Status = SamrRemoveMultipleMembersFromAlias((SAMPR_HANDLE)AliasHandle,
+                                                    &Buffer);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+SamRidToSid(IN SAM_HANDLE ObjectHandle,
+            IN ULONG Rid,
+            OUT PSID *Sid)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
 NTSTATUS
 NTAPI
 SamSetInformationAlias(IN SAM_HANDLE AliasHandle,
@@ -1165,6 +1557,88 @@ SamSetInformationUser(IN SAM_HANDLE UserHandle,
 }
 
 
+NTSTATUS
+NTAPI
+SamSetMemberAttributesOfGroup(IN SAM_HANDLE GroupHandle,
+                              IN ULONG MemberId,
+                              IN ULONG Attributes)
+{
+    NTSTATUS Status;
+
+    TRACE("SamSetMemberAttributesOfGroup(%p %lu 0x%lx)\n",
+          GroupHandle, MemberId, Attributes);
+
+    RpcTryExcept
+    {
+        Status = SamrSetMemberAttributesOfGroup((SAMPR_HANDLE)GroupHandle,
+                                                MemberId,
+                                                Attributes);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+SamSetSecurityObject(IN SAM_HANDLE ObjectHandle,
+                     IN SECURITY_INFORMATION SecurityInformation,
+                     IN PSECURITY_DESCRIPTOR SecurityDescriptor)
+{
+    SAMPR_SR_SECURITY_DESCRIPTOR DescriptorToPass;
+    ULONG Length;
+    NTSTATUS Status;
+
+    TRACE("SamSetSecurityObject(%p %lu %p)\n",
+          ObjectHandle, SecurityInformation, SecurityDescriptor);
+
+    /* Retrieve the length of the relative security descriptor */
+    Length = 0;
+    Status = RtlMakeSelfRelativeSD(SecurityDescriptor,
+                                   NULL,
+                                   &Length);
+    if (Status != STATUS_BUFFER_TOO_SMALL)
+        return STATUS_INVALID_PARAMETER;
+
+
+    /* Allocate a buffer for the security descriptor */
+    DescriptorToPass.Length = Length;
+    DescriptorToPass.SecurityDescriptor = MIDL_user_allocate(Length);
+    if (DescriptorToPass.SecurityDescriptor == NULL)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* Convert the given security descriptor to a relative security descriptor */
+    Status = RtlMakeSelfRelativeSD(SecurityDescriptor,
+                                   (PSECURITY_DESCRIPTOR)DescriptorToPass.SecurityDescriptor,
+                                   &Length);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    RpcTryExcept
+    {
+        Status = SamrSetSecurityObject((SAMPR_HANDLE)ObjectHandle,
+                                       SecurityInformation,
+                                       &DescriptorToPass);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+done:
+    if (DescriptorToPass.SecurityDescriptor != NULL)
+        MIDL_user_free(DescriptorToPass.SecurityDescriptor);
+
+    return Status;
+}
+
+
 NTSTATUS
 NTAPI
 SamShutdownSamServer(IN SAM_HANDLE ServerHandle)
index acdb695..0176a0c 100644 (file)
@@ -1,6 +1,6 @@
 @ stdcall SamAddMemberToAlias(ptr ptr)
-@ stub SamAddMemberToGroup
-@ stub SamAddMultipleMembersToAlias
+@ stdcall SamAddMemberToGroup(ptr long long)
+@ stdcall SamAddMultipleMembersToAlias(ptr ptr long)
 @ stub SamChangePasswordUser2
 @ stub SamChangePasswordUser3
 @ stub SamChangePasswordUser
@@ -11,9 +11,9 @@
 @ stdcall SamCreateGroupInDomain(ptr ptr long ptr ptr)
 @ stdcall SamCreateUser2InDomain(ptr ptr long long ptr ptr ptr)
 @ stdcall SamCreateUserInDomain(ptr ptr long ptr ptr)
-@ stub SamDeleteAlias
-@ stub SamDeleteGroup
-@ stub SamDeleteUser
+@ stdcall SamDeleteAlias(ptr)
+@ stdcall SamDeleteGroup(ptr)
+@ stdcall SamDeleteUser(ptr)
 @ stdcall SamEnumerateAliasesInDomain(ptr ptr ptr long ptr)
 @ stdcall SamEnumerateDomainsInSamServer(ptr ptr ptr long ptr)
 @ stdcall SamEnumerateGroupsInDomain(ptr ptr ptr long ptr)
@@ -22,9 +22,9 @@
 @ stdcall SamGetAliasMembership(ptr long ptr ptr ptr)
 @ stub SamGetCompatibilityMode
 @ stub SamGetDisplayEnumerationIndex
-@ stub SamGetGroupsForUser
+@ stdcall SamGetGroupsForUser(ptr ptr ptr)
 @ stdcall SamGetMembersInAlias(ptr ptr ptr)
-@ stub SamGetMembersInGroup
+@ stdcall SamGetMembersInGroup(ptr ptr ptr ptr)
 @ stdcall SamLookupDomainInSamServer(ptr ptr ptr)
 @ stdcall SamLookupIdsInDomain(ptr long ptr ptr ptr)
 @ stdcall SamLookupNamesInDomain(ptr long ptr ptr ptr)
 @ 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
index b4f0076..242b591 100644 (file)
@@ -83,26 +83,38 @@ static int SIC_LoadOverlayIcon(int icon_idx);
  * NOTES
  *  Creates a new icon as a copy of the passed-in icon, overlayed with a
  *  shortcut image.
+ * FIXME: This should go to the ImageList implementation!
  */
 static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
-{    ICONINFO SourceIconInfo, ShortcutIconInfo, TargetIconInfo;
-    HICON ShortcutIcon, TargetIcon;
-    BITMAP SourceBitmapInfo, ShortcutBitmapInfo;
-    HDC SourceDC = NULL,
-      ShortcutDC = NULL,
-      TargetDC = NULL,
-      ScreenDC = NULL;
-    HBITMAP OldSourceBitmap = NULL,
-      OldShortcutBitmap = NULL,
+{    
+    ICONINFO ShortcutIconInfo, TargetIconInfo;
+    HICON ShortcutIcon = NULL, TargetIcon;
+    BITMAP TargetBitmapInfo, ShortcutBitmapInfo;
+    HDC ShortcutDC = NULL,
+      TargetDC = NULL;
+    HBITMAP OldShortcutBitmap = NULL,
       OldTargetBitmap = NULL;
 
     static int s_imgListIdx = -1;
-
-    /* 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 */
@@ -121,23 +133,25 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
     } else
         ShortcutIcon = NULL;
 
-    if (NULL == ShortcutIcon
-        || ! GetIconInfo(ShortcutIcon, &ShortcutIconInfo)
-        || 0 == GetObjectW(ShortcutIconInfo.hbmColor, sizeof(BITMAP), &ShortcutBitmapInfo))
+    if (!ShortcutIcon || !GetIconInfo(ShortcutIcon, &ShortcutIconInfo))
     {
-      return NULL;
+        goto fail;
+    }
+    
+    /* Is it possible with the ImageLists ? */
+    if(!ShortcutIconInfo.hbmColor)
+    {
+        /* Maybe we'll support this at some point */
+        FIXME("Should draw 1bpp overlay!\n");
+        goto fail;
+    }
+    
+    if(!GetObjectW(ShortcutIconInfo.hbmColor, sizeof(BITMAP), &ShortcutBitmapInfo))
+    {
+        goto fail;
     }
 
-    TargetIconInfo = SourceIconInfo;
-    TargetIconInfo.hbmMask = NULL;
-    TargetIconInfo.hbmColor = NULL;
-
-    /* Setup the source, shortcut and target masks */
-    SourceDC = CreateCompatibleDC(NULL);
-    if (NULL == SourceDC) goto fail;
-    OldSourceBitmap = (HBITMAP)SelectObject(SourceDC, SourceIconInfo.hbmMask);
-    if (NULL == OldSourceBitmap) goto fail;
-
+    /* Setup the masks */
     ShortcutDC = CreateCompatibleDC(NULL);
     if (NULL == ShortcutDC) goto fail;
     OldShortcutBitmap = (HBITMAP)SelectObject(ShortcutDC, ShortcutIconInfo.hbmMask);
@@ -145,44 +159,120 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
 
     TargetDC = CreateCompatibleDC(NULL);
     if (NULL == TargetDC) goto fail;
-    TargetIconInfo.hbmMask = CreateCompatibleBitmap(TargetDC, SourceBitmapInfo.bmWidth,
-                                                    SourceBitmapInfo.bmHeight);
-    if (NULL == TargetIconInfo.hbmMask) goto fail;
-    ScreenDC = GetDC(NULL);
-    if (NULL == ScreenDC) goto fail;
-    TargetIconInfo.hbmColor = CreateCompatibleBitmap(ScreenDC, SourceBitmapInfo.bmWidth,
-                                                     SourceBitmapInfo.bmHeight);
-    ReleaseDC(NULL, ScreenDC);
-    if (NULL == TargetIconInfo.hbmColor) goto fail;
     OldTargetBitmap = (HBITMAP)SelectObject(TargetDC, TargetIconInfo.hbmMask);
     if (NULL == OldTargetBitmap) goto fail;
 
-    /* Create the target mask by ANDing the source and shortcut masks */
-    if (! BitBlt(TargetDC, 0, 0, SourceBitmapInfo.bmWidth, SourceBitmapInfo.bmHeight,
-                 SourceDC, 0, 0, SRCCOPY) ||
-        ! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight,
-                 ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
-                 ShortcutDC, 0, 0, SRCAND))
+    /* Create the complete mask by ANDing the source and shortcut masks.
+     * NOTE: in an ImageList, all icons have the same dimensions */
+    if (!BitBlt(TargetDC, 0, 0, ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
+                ShortcutDC, 0, 0, SRCAND))
     {
       goto fail;
     }
 
-    /* Setup the source and target xor bitmap */
-    if (NULL == SelectObject(SourceDC, SourceIconInfo.hbmColor) ||
-        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)))
     {
@@ -192,11 +282,9 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
     /* Clean up, we're not goto'ing to 'fail' after this so we can be lazy and not set
        handles to NULL */
     SelectObject(TargetDC, OldTargetBitmap);
-    DeleteObject(TargetDC);
+    DeleteDC(TargetDC);
     SelectObject(ShortcutDC, OldShortcutBitmap);
-    DeleteObject(ShortcutDC);
-    SelectObject(SourceDC, OldSourceBitmap);
-    DeleteObject(SourceDC);
+    DeleteDC(ShortcutDC);
 
     /* Create the icon using the bitmaps prepared earlier */
     TargetIcon = CreateIconIndirect(&TargetIconInfo);
@@ -204,19 +292,24 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
     /* CreateIconIndirect copies the bitmaps, so we can release our bitmaps now */
     DeleteObject(TargetIconInfo.hbmColor);
     DeleteObject(TargetIconInfo.hbmMask);
+    /* Delete what GetIconInfo gave us */
+    DeleteObject(ShortcutIconInfo.hbmColor);
+    DeleteObject(ShortcutIconInfo.hbmMask);
+    DestroyIcon(ShortcutIcon);
 
     return TargetIcon;
 
 fail:
     /* Clean up scratch resources we created */
     if (NULL != OldTargetBitmap) SelectObject(TargetDC, OldTargetBitmap);
+    if (NULL != TargetDC) DeleteDC(TargetDC);
+    if (NULL != OldShortcutBitmap) SelectObject(ShortcutDC, OldShortcutBitmap);
+    if (NULL != ShortcutDC) DeleteDC(ShortcutDC);
     if (NULL != TargetIconInfo.hbmColor) DeleteObject(TargetIconInfo.hbmColor);
     if (NULL != TargetIconInfo.hbmMask) DeleteObject(TargetIconInfo.hbmMask);
-    if (NULL != TargetDC) DeleteObject(TargetDC);
-    if (NULL != OldShortcutBitmap) SelectObject(ShortcutDC, OldShortcutBitmap);
-    if (NULL != ShortcutDC) DeleteObject(ShortcutDC);
-    if (NULL != OldSourceBitmap) SelectObject(SourceDC, OldSourceBitmap);
-    if (NULL != SourceDC) DeleteObject(SourceDC);
+    if (NULL != ShortcutIconInfo.hbmColor) DeleteObject(ShortcutIconInfo.hbmColor);
+    if (NULL != ShortcutIconInfo.hbmMask) DeleteObject(ShortcutIconInfo.hbmColor);
+    if (NULL != ShortcutIcon) DestroyIcon(ShortcutIcon);
 
     return NULL;
 }
@@ -228,7 +321,8 @@ fail:
  *  appends an icon pair to the end of the cache
  */
 static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallIcon, HICON hBigIcon, DWORD dwFlags)
-{    LPSIC_ENTRY lpsice;
+{
+    LPSIC_ENTRY lpsice;
     INT ret, index, index1;
     WCHAR path[MAX_PATH];
     TRACE("%s %i %p %p\n", debugstr_w(sSourceFile), dwSourceIndex, hSmallIcon ,hBigIcon);
@@ -247,23 +341,38 @@ static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallI
     index = DPA_InsertPtr(sic_hdpa, 0x7fff, lpsice);
     if ( INVALID_INDEX == index )
     {
-      HeapFree(GetProcessHeap(), 0, lpsice->sSourceFile);
-      SHFree(lpsice);
-      ret = INVALID_INDEX;
+        ret = INVALID_INDEX;
+        goto leave;
     }
-    else
+
+    index = ImageList_AddIcon (ShellSmallIconList, hSmallIcon);
+    index1= ImageList_AddIcon (ShellBigIconList, hBigIcon);
+
+    /* Something went wrong when allocating a new image in the list. Abort. */
+    if((index == -1) || (index1 == -1))
     {
-      index = ImageList_AddIcon (ShellSmallIconList, hSmallIcon);
-      index1= ImageList_AddIcon (ShellBigIconList, hBigIcon);
+        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;
 }
@@ -274,23 +383,23 @@ static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallI
  *  gets small/big icon by number from a file
  */
 static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags)
-{    HICON    hiconLarge=0;
-    HICON    hiconSmall=0;
-    HICON     hiconLargeShortcut;
-    HICON    hiconSmallShortcut;
-
-#if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER)
+{
+    HICON hiconLarge=0;
+    HICON hiconSmall=0;
+    UINT ret;
     static UINT (WINAPI*PrivateExtractIconExW)(LPCWSTR,int,HICON*,HICON*,UINT) = NULL;
 
-    if (!PrivateExtractIconExW) {
+    if (!PrivateExtractIconExW)
+    {
         HMODULE hUser32 = GetModuleHandleA("user32");
         PrivateExtractIconExW = (UINT(WINAPI*)(LPCWSTR,int,HICON*,HICON*,UINT)) GetProcAddress(hUser32, "PrivateExtractIconExW");
     }
 
-        if (PrivateExtractIconExW)
+    if (PrivateExtractIconExW)
+    {
         PrivateExtractIconExW(sSourceFile, dwSourceIndex, &hiconLarge, &hiconSmall, 1);
+    }
     else
-#endif
     {
         PrivateExtractIconsW(sSourceFile, dwSourceIndex, 32, 32, &hiconLarge, NULL, 1, 0);
         PrivateExtractIconsW(sSourceFile, dwSourceIndex, 16, 16, &hiconSmall, NULL, 1, 0);
@@ -298,29 +407,36 @@ static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags)
 
     if ( !hiconLarge ||  !hiconSmall)
     {
-      WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex, debugstr_w(sSourceFile), hiconLarge, hiconSmall);
-      return -1;
+        WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex, debugstr_w(sSourceFile), hiconLarge, hiconSmall);
+        if(hiconLarge) DestroyIcon(hiconLarge);
+        if(hiconSmall) DestroyIcon(hiconSmall);
+        return INVALID_INDEX;
     }
 
     if (0 != (dwFlags & GIL_FORSHORTCUT))
     {
-      hiconLargeShortcut = SIC_OverlayShortcutImage(hiconLarge, TRUE);
-      hiconSmallShortcut = SIC_OverlayShortcutImage(hiconSmall, FALSE);
-      if (NULL != hiconLargeShortcut && NULL != hiconSmallShortcut)
-      {
-        hiconLarge = hiconLargeShortcut;
-        hiconSmall = hiconSmallShortcut;
-      }
-      else
-      {
-        WARN("Failed to create shortcut overlayed icons\n");
-        if (NULL != hiconLargeShortcut) DestroyIcon(hiconLargeShortcut);
-        if (NULL != hiconSmallShortcut) DestroyIcon(hiconSmallShortcut);
-        dwFlags &= ~ GIL_FORSHORTCUT;
-      }
+        HICON hiconLargeShortcut = SIC_OverlayShortcutImage(hiconLarge, TRUE);
+        HICON hiconSmallShortcut = SIC_OverlayShortcutImage(hiconSmall, FALSE);
+        if (NULL != hiconLargeShortcut && NULL != hiconSmallShortcut)
+        {
+            DestroyIcon(hiconLarge);
+            DestroyIcon(hiconSmall);
+            hiconLarge = hiconLargeShortcut;
+            hiconSmall = hiconSmallShortcut;
+        }
+        else
+        {
+            WARN("Failed to create shortcut overlayed icons\n");
+            if (NULL != hiconLargeShortcut) DestroyIcon(hiconLargeShortcut);
+            if (NULL != hiconSmallShortcut) DestroyIcon(hiconSmallShortcut);
+            dwFlags &= ~ GIL_FORSHORTCUT;
+        }
     }
 
-    return SIC_IconAppend (sSourceFile, dwSourceIndex, hiconSmall, hiconLarge, dwFlags);
+    ret = SIC_IconAppend (sSourceFile, dwSourceIndex, hiconSmall, hiconLarge, dwFlags);
+    DestroyIcon(hiconLarge);
+    DestroyIcon(hiconSmall);
+    return ret;
 }
 /*****************************************************************************
  * SIC_GetIconIndex            [internal]
@@ -367,6 +483,7 @@ INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags )
     LeaveCriticalSection(&SHELL32_SicCS);
     return ret;
 }
+
 /*****************************************************************************
  * SIC_Initialize            [internal]
  */
@@ -378,6 +495,7 @@ BOOL SIC_Initialize(void)
     HDC hDC;
     INT bpp;
     DWORD ilMask;
+    BOOL result = FALSE;
 
     TRACE("Entered SIC_Initialize\n");
 
@@ -397,11 +515,11 @@ BOOL SIC_Initialize(void)
     if (!hDC)
     {
         ERR("Failed to create information context (error %d)\n", GetLastError());
-        return FALSE;
+        goto end;
     }
 
     bpp = GetDeviceCaps(hDC, BITSPIXEL);
-    ReleaseDC(NULL, hDC);
+    DeleteDC(hDC);
 
     if (bpp <= 4)
         ilMask = ILC_COLOR4;
@@ -428,61 +546,83 @@ BOOL SIC_Initialize(void)
                                           ilMask,
                                           100,
                                           100);
+    if (!ShellSmallIconList)
+    {
+        ERR("Failed to create the small icon list.\n");
+        goto end;
+    }
 
     ShellBigIconList = ImageList_Create(cx_large,
                                         cy_large,
                                         ilMask,
                                         100,
                                         100);
-    if (ShellSmallIconList)
-    {
-        /* 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
  *
index d443106..4254fd7 100644 (file)
@@ -306,6 +306,38 @@ HidP_GetScaledUsageValue(
     return HidParser_GetScaledUsageValue(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
 }
 
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetUsageValue(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection,
+  IN USAGE  Usage,
+  OUT PULONG  UsageValue,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    HID_PARSER Parser;
+
+    //
+    // sanity check
+    //
+    ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
+
+    //
+    // init parser
+    //
+    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
+
+    //
+    // get scaled usage value
+    //
+    return HidParser_GetUsageValue(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
+}
+
+
 HIDAPI
 NTSTATUS
 NTAPI
@@ -405,24 +437,6 @@ HidP_GetLinkCollectionNodes(
     return STATUS_NOT_IMPLEMENTED;
 }
 
-HIDAPI
-NTSTATUS
-NTAPI
-HidP_GetUsageValue(
-  IN HIDP_REPORT_TYPE  ReportType,
-  IN USAGE  UsagePage,
-  IN USHORT  LinkCollection,
-  IN USAGE  Usage,
-  OUT PULONG  UsageValue,
-  IN PHIDP_PREPARSED_DATA  PreparsedData,
-  IN PCHAR  Report,
-  IN ULONG  ReportLength)
-{
-    UNIMPLEMENTED
-    ASSERT(FALSE);
-    return STATUS_NOT_IMPLEMENTED;
-}
-
 NTSTATUS
 NTAPI
 HidP_SysPowerEvent (
index b713b70..6ba3007 100644 (file)
@@ -37,6 +37,7 @@ MouHid_GetButtonMove(
     OUT PLONG LastY)
 {
     NTSTATUS Status;
+    ULONG ValueX, ValueY;
 
     /* init result */
     *LastX = 0;
@@ -44,16 +45,49 @@ MouHid_GetButtonMove(
 
     /* get scaled usage value x */
     Status =  HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, (PLONG)LastX, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
-    /* FIXME handle error */
-    ASSERT(Status == HIDP_STATUS_SUCCESS);
+    if (Status != HIDP_STATUS_SUCCESS)
+    {
+        /* FIXME: handle more errors */
+        if (Status == HIDP_STATUS_BAD_LOG_PHY_VALUES)
+        {
+            /* FIXME: assume it operates in absolute mode */
+            DeviceExtension->MouseAbsolute = TRUE;
+
+            /* get unscaled value */
+            Status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, (PULONG)&ValueX, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
+
+            /* FIXME handle error */
+            ASSERT(Status == HIDP_STATUS_SUCCESS);
+
+            /* absolute pointing devices values need be in range 0 - 0xffff */
+            ASSERT(DeviceExtension->ValueCapsX.LogicalMax > 0);
+
+            *LastX = (ValueX * 0xFFFF) / DeviceExtension->ValueCapsX.LogicalMax;
+        }
+    }
 
     /* get scaled usage value y */
     Status =  HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, (PLONG)LastY, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
-    /* FIXME handle error */
-    ASSERT(Status == HIDP_STATUS_SUCCESS);
+    if (Status != HIDP_STATUS_SUCCESS)
+    {
+        // FIXME: handle more errors
+        if (Status == HIDP_STATUS_BAD_LOG_PHY_VALUES)
+        {
+            // assume it operates in absolute mode
+            DeviceExtension->MouseAbsolute = TRUE;
 
-}
+            // get unscaled value
+            Status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, (PULONG)&ValueY, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
 
+            /* FIXME handle error */
+            ASSERT(Status == HIDP_STATUS_SUCCESS);
+
+            /* absolute pointing devices values need be in range 0 - 0xffff */
+            ASSERT(DeviceExtension->ValueCapsY.LogicalMax);
+            *LastY = (ValueY * 0xFFFF) / DeviceExtension->ValueCapsY.LogicalMax;
+        }
+    }
+}
 
 VOID
 MouHid_GetButtonFlags(
@@ -132,6 +166,12 @@ MouHid_GetButtonFlags(
     TempList = DeviceExtension->CurrentUsageList;
     DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList;
     DeviceExtension->PreviousUsageList = TempList;
+
+    if (DeviceExtension->MouseAbsolute)
+    {
+        // mouse operates absolute
+        *ButtonFlags |= MOUSE_MOVE_ABSOLUTE;
+    }
 }
 
 VOID
@@ -195,12 +235,12 @@ MouHid_ReadCompletion(
         return STATUS_MORE_PROCESSING_REQUIRED;
     }
 
-    /* get mouse change flags */
-    MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags);
-
     /* get mouse change */
     MouHid_GetButtonMove(DeviceExtension, &LastX, &LastY);
 
+    /* get mouse change flags */
+    MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags);
+
     /* init input data */
     RtlZeroMemory(&MouseInputData, sizeof(MOUSE_INPUT_DATA));
 
@@ -227,6 +267,12 @@ MouHid_ReadCompletion(
         }
     }
 
+    DPRINT("[MOUHID] ReportData %02x %02x %02x %02x %02x %02x %02x\n",
+        DeviceExtension->Report[0] & 0xFF,
+        DeviceExtension->Report[1] & 0xFF, DeviceExtension->Report[2] & 0xFF,
+        DeviceExtension->Report[3] & 0xFF, DeviceExtension->Report[4] & 0xFF,
+        DeviceExtension->Report[5] & 0xFF, DeviceExtension->Report[6] & 0xFF);
+
     DPRINT("[MOUHID] LastX %ld LastY %ld Flags %x ButtonData %x\n", MouseInputData.LastX, MouseInputData.LastY, MouseInputData.ButtonFlags, MouseInputData.ButtonData);
 
     /* dispatch mouse action */
@@ -700,10 +746,10 @@ MouHid_StartDevice(
     DeviceExtension->PreparsedData = PreparsedData;
 
     ValueCapsLength = 1;
-    HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, &ValueCaps, &ValueCapsLength, PreparsedData);
+    HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, &DeviceExtension->ValueCapsX, &ValueCapsLength, PreparsedData);
 
     ValueCapsLength = 1;
-    HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, &ValueCaps, &ValueCapsLength, PreparsedData);
+    HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, &DeviceExtension->ValueCapsY, &ValueCapsLength, PreparsedData);
 
     /* now check for wheel mouse support */
     ValueCapsLength = 1;
index 78048fd..e177a2f 100644 (file)
@@ -109,6 +109,22 @@ typedef struct
     //
     UCHAR StopReadReport;
 
+    //
+    // mouse absolute
+    //
+    UCHAR MouseAbsolute;
+
+    //
+    // value caps x
+    //
+    HIDP_VALUE_CAPS ValueCapsX;
+
+    //
+    // value caps y button
+    //
+    HIDP_VALUE_CAPS ValueCapsY;
+
+
 }MOUHID_DEVICE_EXTENSION, *PMOUHID_DEVICE_EXTENSION;
 
 #define WHEEL_DELTA 120
index df273ee..958f017 100644 (file)
@@ -474,8 +474,11 @@ USBD_ParseDescriptors(
            return CommonDescriptor;
        }
 
-       /* sanity check */
-       ASSERT(CommonDescriptor->bLength);
+       if (CommonDescriptor->bLength == 0)
+       {
+           /* invalid usb descriptor */
+           return NULL;
+       }
 
        /* move to next descriptor */
        CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
index ec56674..65c529c 100644 (file)
@@ -819,6 +819,7 @@ CreateDeviceIds(
     LPWSTR DeviceString;
     WCHAR Buffer[200];
     PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
+    PHUB_DEVICE_EXTENSION HubDeviceExtension;
     PUSB_DEVICE_DESCRIPTOR DeviceDescriptor;
     PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
@@ -828,6 +829,9 @@ CreateDeviceIds(
     //
     UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension;
 
+    // get hub device extension
+    HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbChildExtension->ParentDeviceObject->DeviceExtension;
+
     //
     // get device descriptor
     //
@@ -1011,10 +1015,12 @@ CreateDeviceIds(
     //
     if (UsbChildExtension->DeviceDesc.iSerialNumber)
     {
+       LPWSTR SerialBuffer = NULL;
+
         Status = GetUsbStringDescriptor(UsbChildDeviceObject,
                                         UsbChildExtension->DeviceDesc.iSerialNumber,
                                         0,
-                                        (PVOID*)&UsbChildExtension->usInstanceId.Buffer,
+                                        (PVOID*)&SerialBuffer,
                                         &UsbChildExtension->usInstanceId.Length);
         if (!NT_SUCCESS(Status))
         {
@@ -1022,15 +1028,31 @@ CreateDeviceIds(
             return Status;
         }
 
-        UsbChildExtension->usInstanceId.MaximumLength = UsbChildExtension->usInstanceId.Length;
-        DPRINT("Usb InstanceId %wZ\n", &UsbChildExtension->usInstanceId);
+        // construct instance id buffer
+        Index = swprintf(Buffer, L"%04d&%s", HubDeviceExtension->InstanceCount, SerialBuffer) + 1;
+        UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
+        if (UsbChildExtension->usInstanceId.Buffer == NULL)
+        {
+            DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR));
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            return Status;
+        }
+
+        //
+        // copy instance id
+        //
+        RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR));
+        UsbChildExtension->usInstanceId.Length = UsbChildExtension->usInstanceId.MaximumLength = Index * sizeof(WCHAR);
+        ExFreePool(SerialBuffer);
+
+        DPRINT("Usb InstanceId %wZ InstanceCount %x\n", &UsbChildExtension->usInstanceId, HubDeviceExtension->InstanceCount);
     }
     else
     {
        //
        // the device did not provide a serial number, lets create a pseudo instance id
        //
-       Index = swprintf(Buffer, L"0&%04d", UsbChildExtension->PortNumber) + 1;
+       Index = swprintf(Buffer, L"%04d&%04d", HubDeviceExtension->InstanceCount, UsbChildExtension->PortNumber) + 1;
        UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
        if (UsbChildExtension->usInstanceId.Buffer == NULL)
        {
@@ -1304,6 +1326,7 @@ CreateUsbChildDeviceObject(
     }
 
     HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] = NewChildDeviceObject;
+    HubDeviceExtension->InstanceCount++;
 
     IoInvalidateDeviceRelations(RootHubDeviceObject, BusRelations);
     return STATUS_SUCCESS;
index 939a9f3..6c561b9 100644 (file)
@@ -558,6 +558,7 @@ USBHUB_PdoHandlePnp(
     ULONG Index;
     ULONG bFound;
     PDEVICE_RELATIONS DeviceRelation;
+    PDEVICE_OBJECT ParentDevice;
 
     UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
     Stack = IoGetCurrentIrpStackLocation(Irp);
@@ -645,6 +646,7 @@ USBHUB_PdoHandlePnp(
         {
             PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension;
             PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface;
+            ParentDevice = UsbChildExtension->ParentDeviceObject;
 
             DPRINT("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
 
@@ -671,10 +673,13 @@ USBHUB_PdoHandlePnp(
             Irp->IoStatus.Status = STATUS_SUCCESS;
             IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
+            /* delete device */
+            IoDeleteDevice(DeviceObject);
+
             if (bFound)
             {
-                /* Delete the device object */
-                IoDeleteDevice(DeviceObject);
+                /* invalidate device relations */
+                IoInvalidateDeviceRelations(ParentDevice, BusRelations);
             }
 
             return STATUS_SUCCESS;
@@ -731,6 +736,12 @@ USBHUB_PdoHandlePnp(
             IoSkipCurrentIrpStackLocation(Irp);
             return IoCallDriver(UsbChildExtension->ParentDeviceObject, Irp);
         }
+        case IRP_MN_SURPRISE_REMOVAL:
+        {
+            DPRINT("[USBHUB] HandlePnp IRP_MN_SURPRISE_REMOVAL\n");
+            Status = STATUS_SUCCESS;
+            break;
+        }
         default:
         {
             DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
index 2333775..52d62e2 100644 (file)
@@ -103,8 +103,9 @@ typedef struct _HUB_DEVICE_EXTENSION
     PVOID RootHubHandle;
     USB_BUS_INTERFACE_USBDI_V2 DeviceInterface;
 
-
     UNICODE_STRING SymbolicLinkName;
+    ULONG InstanceCount;
+
 } HUB_DEVICE_EXTENSION, *PHUB_DEVICE_EXTENSION;
 
 // createclose.c
index 0751842..a9f408d 100644 (file)
@@ -125,10 +125,19 @@ USBSTOR_FdoHandleRemoveDevice(
     IN OUT PIRP Irp)
 {
     NTSTATUS Status;
+    ULONG Index;
 
-    DPRINT("Handling FDO removal\n");
+    DPRINT("Handling FDO removal %p\n", DeviceObject);
 
-    /* We don't need to request removal of our children here */
+    /* FIXME: wait for devices finished processing */
+    for(Index = 0; Index < 16; Index++)
+    {
+        if (DeviceExtension->ChildPDO[Index] != NULL)
+        {
+            DPRINT("Deleting PDO %p RefCount %x AttachedDevice %p \n", DeviceExtension->ChildPDO[Index], DeviceExtension->ChildPDO[Index]->ReferenceCount, DeviceExtension->ChildPDO[Index]->AttachedDevice);
+            IoDeleteDevice(DeviceExtension->ChildPDO[Index]);
+        }
+    }
 
     /* Send the IRP down the stack */
     IoSkipCurrentIrpStackLocation(Irp);
@@ -264,7 +273,7 @@ USBSTOR_FdoHandleStartDevice(
         //
         // create pdo
         //
-        Status = USBSTOR_CreatePDO(DeviceObject, Index, &DeviceExtension->ChildPDO[Index]);
+        Status = USBSTOR_CreatePDO(DeviceObject, Index);
 
         //
         // check for failure
@@ -282,6 +291,7 @@ USBSTOR_FdoHandleStartDevice(
         // increment pdo index
         //
         Index++;
+        DeviceExtension->InstanceCount++;
 
     }while(Index < DeviceExtension->MaxLUN);
 
@@ -340,8 +350,20 @@ USBSTOR_FdoHandlePnp(
 
     switch(IoStack->MinorFunction)
     {
+       case IRP_MN_SURPRISE_REMOVAL:
+       {
+           DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject);
+           Irp->IoStatus.Status = STATUS_SUCCESS;
+
+            //
+            // forward irp to next device object
+            //
+            IoSkipCurrentIrpStackLocation(Irp);
+            return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
+       }
        case IRP_MN_QUERY_DEVICE_RELATIONS:
        {
+           DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject);
            Status = USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp);
            break;
        }
index 9e293df..f7a2a65 100644 (file)
@@ -676,9 +676,9 @@ USBSTOR_PdoHandleQueryInstanceId(
     else
     {
         //
-        // FIXME: should use some random value
+        // use instance count and LUN
         //
-        swprintf(Buffer, L"%s&%d", L"00000000", PDODeviceExtension->LUN);
+        swprintf(Buffer, L"%04d&%d", FDODeviceExtension->InstanceCount, PDODeviceExtension->LUN);
     }
 
     //
@@ -897,7 +897,7 @@ USBSTOR_PdoHandlePnp(
                // check if no unique id
                //
                Caps = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
-               Caps->UniqueID = TRUE; //FIXME
+               Caps->UniqueID = FALSE; // no unique id is supported
                Caps->Removable = TRUE; //FIXME
            }
            break;
@@ -929,6 +929,11 @@ USBSTOR_PdoHandlePnp(
            Status = STATUS_SUCCESS;
            break;
        }
+       case IRP_MN_SURPRISE_REMOVAL:
+       {
+           Status = STATUS_SUCCESS;
+           break;
+       }
        default:
         {
             //
@@ -1256,13 +1261,19 @@ USBSTOR_SendFormatCapacityIrp(
 NTSTATUS
 USBSTOR_CreatePDO(
     IN PDEVICE_OBJECT DeviceObject,
-    IN UCHAR LUN,
-    OUT PDEVICE_OBJECT *ChildDeviceObject)
+    IN UCHAR LUN)
 {
     PDEVICE_OBJECT PDO;
     NTSTATUS Status;
     PPDO_DEVICE_EXTENSION PDODeviceExtension;
     PUFI_INQUIRY_RESPONSE Response;
+    PFDO_DEVICE_EXTENSION FDODeviceExtension;
+
+    //
+    // get device extension
+    //
+    FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
 
     //
     // create child device object
@@ -1292,7 +1303,7 @@ USBSTOR_CreatePDO(
     RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
     PDODeviceExtension->Common.IsFDO = FALSE;
     PDODeviceExtension->LowerDeviceObject = DeviceObject;
-    PDODeviceExtension->PDODeviceObject = ChildDeviceObject;
+    PDODeviceExtension->PDODeviceObject = &FDODeviceExtension->ChildPDO[LUN];
     PDODeviceExtension->Self = PDO;
     PDODeviceExtension->LUN = LUN;
 
@@ -1309,7 +1320,7 @@ USBSTOR_CreatePDO(
     //
     // output device object
     //
-    *ChildDeviceObject = PDO;
+    FDODeviceExtension->ChildPDO[LUN] = PDO;
 
     //
     // send inquiry command by irp
index 29ef1ce..3fb4d3c 100644 (file)
@@ -71,6 +71,7 @@ typedef struct
     PSCSI_REQUEST_BLOCK LastTimerActiveSrb;                                              // last timer tick active srb
     ULONG SrbErrorHandlingActive;                                                        // error handling of srb is activated
     ULONG TimerWorkQueueEnabled;                                                         // timer work queue enabled
+    ULONG InstanceCount;                                                                 // pdo instance count
 }FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
 
 typedef struct
@@ -364,8 +365,7 @@ USBSTOR_PdoHandlePnp(
 NTSTATUS
 USBSTOR_CreatePDO(
     IN PDEVICE_OBJECT DeviceObject,
-    IN UCHAR LUN,
-    OUT PDEVICE_OBJECT *ChildDeviceObject);
+    IN UCHAR LUN);
 
 //---------------------------------------------------------------------
 //
index 69b5e34..cb0af84 100644 (file)
@@ -271,6 +271,12 @@ typedef enum _GROUP_INFORMATION_CLASS
     GroupReplicationInformation
 } GROUP_INFORMATION_CLASS;
 
+typedef struct _GROUP_MEMBERSHIP
+{
+    ULONG RelativeId;
+    ULONG Attributes;
+} GROUP_MEMBERSHIP, *PGROUP_MEMBERSHIP;
+
 typedef enum _USER_INFORMATION_CLASS
 {
     UserGeneralInformation = 1,
@@ -322,6 +328,12 @@ SamAddMemberToGroup(IN SAM_HANDLE GroupHandle,
                     IN ULONG MemberId,
                     IN ULONG Attributes);
 
+NTSTATUS
+NTAPI
+SamAddMultipleMembersToAlias(IN SAM_HANDLE AliasHandle,
+                             IN PSID *MemberIds,
+                             IN ULONG MemberCount);
+
 NTSTATUS
 NTAPI
 SamCloseHandle(IN SAM_HANDLE SamHandle);
@@ -367,6 +379,18 @@ SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
                       OUT PSAM_HANDLE UserHandle,
                       OUT PULONG RelativeId);
 
+NTSTATUS
+NTAPI
+SamDeleteAlias(IN SAM_HANDLE AliasHandle);
+
+NTSTATUS
+NTAPI
+SamDeleteGroup(IN SAM_HANDLE GroupHandle);
+
+NTSTATUS
+NTAPI
+SamDeleteUser(IN SAM_HANDLE UserHandle);
+
 NTSTATUS
 NTAPI
 SamEnumerateAliasesInDomain(IN SAM_HANDLE DomainHandle,
@@ -412,12 +436,25 @@ SamGetAliasMembership(IN SAM_HANDLE DomainHandle,
                       OUT PULONG MembershipCount,
                       OUT PULONG *Aliases);
 
+NTSTATUS
+NTAPI
+SamGetGroupsForUser(IN SAM_HANDLE UserHandle,
+                    OUT PGROUP_MEMBERSHIP *Groups,
+                    OUT PULONG MembershipCount);
+
 NTSTATUS
 NTAPI
 SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
                      OUT PSID **MemberIds,
                      OUT PULONG MemberCount);
 
+NTSTATUS
+NTAPI
+SamGetMembersInGroup(IN SAM_HANDLE GroupHandle,
+                     OUT PULONG *MemberIds,
+                     OUT PULONG *Attributes,
+                     OUT PULONG MemberCount);
+
 NTSTATUS
 NTAPI
 SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
@@ -492,11 +529,39 @@ SamQueryInformationUser(IN SAM_HANDLE UserHandle,
                         IN USER_INFORMATION_CLASS UserInformationClass,
                         OUT PVOID *Buffer);
 
+NTSTATUS
+NTAPI
+SamQuerySecurityObject(IN SAM_HANDLE ObjectHandle,
+                       IN SECURITY_INFORMATION SecurityInformation,
+                       OUT PSECURITY_DESCRIPTOR *SecurityDescriptor);
+
 NTSTATUS
 NTAPI
 SamRemoveMemberFromAlias(IN SAM_HANDLE AliasHandle,
                          IN PSID MemberId);
 
+NTSTATUS
+NTAPI
+SamRemoveMemberFromForeignDomain(IN SAM_HANDLE DomainHandle,
+                                 IN PSID MemberId);
+
+NTSTATUS
+NTAPI
+SamRemoveMemberFromGroup(IN SAM_HANDLE GroupHandle,
+                         IN ULONG MemberId);
+
+NTSTATUS
+NTAPI
+SamRemoveMultipleMembersFromAlias(IN SAM_HANDLE AliasHandle,
+                                  IN PSID *MemberIds,
+                                  IN ULONG MemberCount);
+
+NTSTATUS
+NTAPI
+SamRidToSid(IN SAM_HANDLE ObjectHandle,
+            IN ULONG Rid,
+            OUT PSID *Sid);
+
 NTSTATUS
 NTAPI
 SamSetInformationAlias(IN SAM_HANDLE AliasHandle,
@@ -521,6 +586,18 @@ SamSetInformationUser(IN SAM_HANDLE UserHandle,
                       IN USER_INFORMATION_CLASS UserInformationClass,
                       IN PVOID Buffer);
 
+NTSTATUS
+NTAPI
+SamSetMemberAttributesOfGroup(IN SAM_HANDLE GroupHandle,
+                              IN ULONG MemberId,
+                              IN ULONG Attributes);
+
+NTSTATUS
+NTAPI
+SamSetSecurityObject(IN SAM_HANDLE ObjectHandle,
+                     IN SECURITY_INFORMATION SecurityInformation,
+                     IN PSECURITY_DESCRIPTOR SecurityDescriptor);
+
 NTSTATUS
 NTAPI
 SamShutdownSamServer(IN SAM_HANDLE ServerHandle);
index 3ff5467..96f1640 100644 (file)
@@ -99,11 +99,13 @@ typedef struct _SAMPR_SR_SECURITY_DESCRIPTOR
     [size_is(Length)] unsigned char* SecurityDescriptor;
 } SAMPR_SR_SECURITY_DESCRIPTOR, *PSAMPR_SR_SECURITY_DESCRIPTOR;
 
+cpp_quote("#ifndef _NTSAM_")
 typedef struct _GROUP_MEMBERSHIP
 {
     unsigned long RelativeId;
     unsigned long Attributes;
 } GROUP_MEMBERSHIP, *PGROUP_MEMBERSHIP;
+cpp_quote("#endif")
 
 typedef struct _SAMPR_GET_GROUPS_BUFFER
 {
index 60daf9b..2550cf4 100644 (file)
 #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
index 1420da7..ee77899 100644 (file)
@@ -563,6 +563,103 @@ HidParser_UsesReportId(
 
 }
 
+HIDPARSER_STATUS
+HidParser_GetUsageValueWithReport(
+    IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType,
+    IN USAGE UsagePage,
+    IN USAGE  Usage,
+    OUT PULONG UsageValue,
+    IN PCHAR ReportDescriptor,
+    IN ULONG ReportDescriptorLength)
+{
+    ULONG Index;
+    PHID_REPORT Report;
+    USHORT CurrentUsagePage;
+    PHID_REPORT_ITEM ReportItem;
+    ULONG Data;
+
+    //
+    // get report
+    //
+    Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
+    if (!Report)
+    {
+        //
+        // no such report
+        //
+        return HIDPARSER_STATUS_REPORT_NOT_FOUND;
+    }
+
+    if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
+    {
+        //
+        // invalid report descriptor length
+        //
+        return HIDPARSER_STATUS_INVALID_REPORT_LENGTH;
+    }
+
+    for(Index = 0; Index < Report->ItemCount; Index++)
+    {
+        //
+        // get report item
+        //
+        ReportItem = &Report->Items[Index];
+
+        //
+        // check usage page
+        //
+        CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
+
+        //
+        // does usage page match
+        //
+        if (UsagePage != CurrentUsagePage)
+            continue;
+
+        //
+        // does the usage match
+        //
+        if (Usage != (ReportItem->UsageMinimum & 0xFFFF))
+            continue;
+
+        //
+        // check if the specified usage is activated
+        //
+        ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
+
+        //
+        // one extra shift for skipping the prepended report id
+        //
+        Data = 0;
+        Parser->Copy(&Data, &ReportDescriptor[ReportItem->ByteOffset +1], min(sizeof(ULONG), ReportDescriptorLength - (ReportItem->ByteOffset + 1)));
+        //Data = ReportDescriptor[ReportItem->ByteOffset + 1];
+
+        //
+        // shift data
+        //
+        Data >>= ReportItem->Shift;
+
+        //
+        // clear unwanted bits
+        //
+        Data &= ReportItem->Mask;
+
+        //
+        // store result
+        //
+        *UsageValue = Data;
+        return HIDPARSER_STATUS_SUCCESS;
+    }
+
+    //
+    // usage not found
+    //
+    return HIDPARSER_STATUS_USAGE_NOT_FOUND;
+}
+
+
 
 HIDPARSER_STATUS
 HidParser_GetScaledUsageValueWithReport(
@@ -652,11 +749,18 @@ HidParser_GetScaledUsageValueWithReport(
             //
             // logical boundaries are signed values
             //
+
+            // FIXME: scale with physical min/max
             if ((Data & ~(ReportItem->Mask >> 1)) != 0)
             {
                 Data |= ~ReportItem->Mask;
             }
         }
+        else
+        {
+            // HACK: logical boundaries are absolute values
+            return HIDPARSER_STATUS_BAD_LOG_PHY_VALUES;
+        }
 
         //
         // store result
index c38b8e1..cc27cd8 100644 (file)
@@ -34,6 +34,8 @@ TranslateHidParserStatus(
             return HIDP_STATUS_I8042_TRANS_UNKNOWN;
         case HIDPARSER_STATUS_COLLECTION_NOT_FOUND:
             return HIDP_STATUS_NOT_IMPLEMENTED; //FIXME
+        case HIDPARSER_STATUS_BAD_LOG_PHY_VALUES:
+            return HIDP_STATUS_BAD_LOG_PHY_VALUES;
     }
     DPRINT1("TranslateHidParserStatus Status %ld not implemented\n", Status);
     return HIDP_STATUS_NOT_IMPLEMENTED;
@@ -952,9 +954,54 @@ HidParser_GetUsageValue(
     IN PCHAR  Report,
     IN ULONG  ReportLength)
 {
-    UNIMPLEMENTED
-    ASSERT(FALSE);
-    return STATUS_NOT_IMPLEMENTED;
+    HIDPARSER_STATUS ParserStatus;
+
+    //
+    // FIXME: implement searching in specific collection
+    //
+    ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
+
+    if (ReportType == HidP_Input)
+    {
+        //
+        // input report
+        //
+        ParserStatus = HidParser_GetUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
+    }
+    else if (ReportType == HidP_Output)
+    {
+        //
+        // input report
+        //
+        ParserStatus = HidParser_GetUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
+    }
+    else if (ReportType == HidP_Feature)
+    {
+        //
+        // input report
+        //
+        ParserStatus = HidParser_GetUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_FEATURE,  UsagePage, Usage, UsageValue, Report, ReportLength);
+    }
+    else
+    {
+        //
+        // invalid report type
+        //
+        return HIDP_STATUS_INVALID_REPORT_TYPE;
+    }
+
+    if (ParserStatus == HIDPARSER_STATUS_SUCCESS)
+    {
+        //
+        // success
+        //
+        return HIDP_STATUS_SUCCESS;
+    }
+
+    //
+    // translate error
+    //
+    return TranslateHidParserStatus(ParserStatus);
 }
 
 NTSTATUS
index 425c208..ed7a616 100644 (file)
@@ -48,7 +48,8 @@ typedef enum
     HIDPARSER_STATUS_INVALID_REPORT_TYPE = -6,
     HIDPARSER_STATUS_BUFFER_TOO_SMALL = -7,
     HIDPARSER_STATUS_USAGE_NOT_FOUND = -8,
-    HIDPARSER_STATUS_I8042_TRANS_UNKNOWN = -9
+    HIDPARSER_STATUS_I8042_TRANS_UNKNOWN = -9,
+    HIDPARSER_STATUS_BAD_LOG_PHY_VALUES = -10
 }HIDPARSER_STATUS_CODES;
 
 typedef struct
@@ -200,6 +201,7 @@ HidParser_GetLinkCollectionNodes(
     OUT PHIDP_LINK_COLLECTION_NODE  LinkCollectionNodes,
     IN OUT PULONG  LinkCollectionNodesLength);
 
+
 HIDAPI
 NTSTATUS
 NTAPI
index ef0d7f3..a7126df 100644 (file)
@@ -327,6 +327,17 @@ HidParser_GetScaledUsageValueWithReport(
     IN PCHAR ReportDescriptor,
     IN ULONG ReportDescriptorLength);
 
+HIDPARSER_STATUS
+HidParser_GetUsageValueWithReport(
+    IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType,
+    IN USAGE UsagePage,
+    IN USAGE  Usage,
+    OUT PULONG UsageValue,
+    IN PCHAR ReportDescriptor,
+    IN ULONG ReportDescriptorLength);
+
 /* parser.c */
 
 HIDPARSER_STATUS
index dcc4d0d..1189120 100644 (file)
@@ -285,6 +285,11 @@ PoVolumeDevice(
     IN PDEVICE_OBJECT DeviceObject
 );
 
+VOID
+NTAPI
+PoRemoveVolumeDevice(
+    IN PDEVICE_OBJECT DeviceObject);
+
 //
 // Power State routines
 //
index 0b1a886..a0e1961 100644 (file)
@@ -1035,6 +1035,9 @@ IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
     /* Set the pending delete flag */
     IoGetDevObjExtension(DeviceObject)->ExtensionFlags |= DOE_DELETE_PENDING;
 
+    /* Unlink with the power manager */
+    if (DeviceObject->Vpb) PoRemoveVolumeDevice(DeviceObject);
+
     /* Check if the device object can be unloaded */
     if (!DeviceObject->ReferenceCount) IopUnloadDevice(DeviceObject);
 }
index 15aaebf..7700302 100644 (file)
@@ -97,7 +97,52 @@ PoVolumeDevice(IN PDEVICE_OBJECT DeviceObject)
         KeReleaseGuardedMutex(&PopVolumeLock);
     }
 }
-    
+
+VOID
+NTAPI
+PoRemoveVolumeDevice(IN PDEVICE_OBJECT DeviceObject)
+{
+    PDEVICE_OBJECT_POWER_EXTENSION Dope;
+    PEXTENDED_DEVOBJ_EXTENSION DeviceExtension;
+    KIRQL OldIrql;
+    PAGED_CODE();
+
+    /* If the device already has the dope, return it */
+    DeviceExtension = IoGetDevObjExtension(DeviceObject);
+    if (!DeviceExtension->Dope)
+    {
+        /* no dope */
+        return;
+    }
+
+    /* Make sure we can flush safely */
+    KeAcquireGuardedMutex(&PopVolumeLock);
+
+    /* Get dope from device */
+    Dope = (PDEVICE_OBJECT_POWER_EXTENSION)DeviceExtension->Dope;
+
+    if (Dope->Volume.Flink)
+    {
+        /* Remove from volume from list */
+        RemoveEntryList(&Dope->Volume);
+    }
+
+    /* Allow flushes to go through */
+    KeReleaseGuardedMutex(&PopVolumeLock);
+
+    /* Now remove dope from device object */
+    KeAcquireSpinLock(&PopDopeGlobalLock, &OldIrql);
+
+    /* remove from dev obj */
+    DeviceExtension->Dope = NULL;
+
+    /* Release lock */
+    KeReleaseSpinLock(&PopDopeGlobalLock, OldIrql);
+
+    /* Free dope */
+    ExFreePoolWithTag(Dope, 'Dope');
+}
+
 VOID
 NTAPI
 PopFlushVolumeWorker(IN PVOID Context)
index fcc03f1..45acd94 100644 (file)
@@ -50,11 +50,15 @@ InitBrushImpl(VOID)
 
 VOID
 NTAPI
-EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
+EBRUSHOBJ_vInit(EBRUSHOBJ *pebo,
+    PBRUSH pbrush,
+    PSURFACE psurf,
+    COLORREF crBackgroundClr,
+    COLORREF crForegroundClr,
+    PPALETTE ppalDC)
 {
     ASSERT(pebo);
     ASSERT(pbrush);
-    ASSERT(pdc);
 
     pebo->BrushObject.flColorType = 0;
     pebo->BrushObject.pvRbrush = NULL;
@@ -63,20 +67,24 @@ EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
     pebo->flattrs = pbrush->flAttrs;
 
     /* Initialize 1 bpp fore and back colors */
-    pebo->crCurrentBack = pdc->pdcattr->crBackgroundClr;
-    pebo->crCurrentText = pdc->pdcattr->crForegroundClr;
+    pebo->crCurrentBack = crBackgroundClr;
+    pebo->crCurrentText = crForegroundClr;
 
-    pebo->psurfTrg = pdc->dclevel.pSurface;
+    pebo->psurfTrg = psurf;
     /* We are initializing for a new memory DC */
     if(!pebo->psurfTrg)
         pebo->psurfTrg = psurfDefaultBitmap;
     ASSERT(pebo->psurfTrg);
     ASSERT(pebo->psurfTrg->ppal);
 
+    /* Initialize palettes */
     pebo->ppalSurf = pebo->psurfTrg->ppal;
     GDIOBJ_vReferenceObjectByPointer(&pebo->ppalSurf->BaseObject);
-    pebo->ppalDC = pdc->dclevel.ppal;
+    pebo->ppalDC = ppalDC;
+    if(!pebo->ppalDC)
+        pebo->ppalDC = gppalDefault;
     GDIOBJ_vReferenceObjectByPointer(&pebo->ppalDC->BaseObject);
+    pebo->ppalDIB = NULL;
 
     if (pbrush->flAttrs & BR_IS_NULL)
     {
@@ -99,6 +107,16 @@ EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
     }
 }
 
+VOID
+NTAPI
+EBRUSHOBJ_vInitFromDC(EBRUSHOBJ *pebo,
+    PBRUSH pbrush, PDC pdc)
+{
+    EBRUSHOBJ_vInit(pebo, pbrush, pdc->dclevel.pSurface,
+        pdc->pdcattr->crBackgroundClr, pdc->pdcattr->crForegroundClr,
+        pdc->dclevel.ppal);
+}
+
 VOID
 FASTCALL
 EBRUSHOBJ_vSetSolidRGBColor(EBRUSHOBJ *pebo, COLORREF crColor)
@@ -157,13 +175,15 @@ EBRUSHOBJ_vCleanup(EBRUSHOBJ *pebo)
 
 VOID
 NTAPI
-EBRUSHOBJ_vUpdate(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
+EBRUSHOBJ_vUpdateFromDC(EBRUSHOBJ *pebo,
+    PBRUSH pbrush,
+    PDC pdc)
 {
     /* Cleanup the brush */
     EBRUSHOBJ_vCleanup(pebo);
 
     /* Reinitialize */
-    EBRUSHOBJ_vInit(pebo, pbrush, pdc);
+    EBRUSHOBJ_vInitFromDC(pebo, pbrush, pdc);
 }
 
 /**
index f9c27d8..98a1b02 100644 (file)
@@ -600,6 +600,21 @@ EXLATEOBJ_vInitXlateFromDCs(
     pexlo->ppalDstDc = pdcDst->dclevel.ppal;
 }
 
+VOID NTAPI EXLATEOBJ_vInitSrcMonoXlate(
+    PEXLATEOBJ pexlo,
+    PPALETTE ppalDst,
+    COLORREF crBackgroundClr,
+    COLORREF crForegroundClr)
+{
+    /* Normal initialisation, with mono palette as source */
+    EXLATEOBJ_vInitialize(pexlo,
+                          gppalMono,
+                          ppalDst,
+                          0,
+                          crBackgroundClr,
+                          crForegroundClr);
+}
+
 VOID
 NTAPI
 EXLATEOBJ_vCleanup(PEXLATEOBJ pexlo)
index e38b1c5..7c5dba4 100644 (file)
@@ -7,9 +7,7 @@
  */
 
 #include <win32k.h>
-
-#define NDEBUG
-#include <debug.h>
+DBG_DEFAULT_CHANNEL(GdiBlt);
 
 #define ROP_USES_SOURCE(Rop)  (((((Rop) & 0xCC0000) >> 2) != ((Rop) & 0x330000)) || ((((Rop) & 0xCC000000) >> 2) != ((Rop) & 0x33000000)))
 #define ROP_USES_MASK(Rop)    (((Rop) & 0xFF000000) != (((Rop) & 0xff0000) << 8))
@@ -49,12 +47,12 @@ NtGdiAlphaBlend(
         return FALSE;
     }
 
-    DPRINT("Locking DCs\n");
+    TRACE("Locking DCs\n");
     ahDC[0] = hDCDest;
     ahDC[1] = hDCSrc ;
     if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
     {
-        DPRINT1("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
+        WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
         EngSetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
@@ -102,7 +100,7 @@ NtGdiAlphaBlend(
     }
 
     /* Prepare DCs for blit */
-    DPRINT("Preparing DCs for blit\n");
+    TRACE("Preparing DCs for blit\n");
     DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
 
     /* Determine surfaces to be used in the bitblt */
@@ -124,7 +122,7 @@ NtGdiAlphaBlend(
     EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
 
     /* Perform the alpha blend operation */
-    DPRINT("Performing the alpha blend\n");
+    TRACE("Performing the alpha blend\n");
     bResult = IntEngAlphaBlend(&BitmapDest->SurfObj,
                                &BitmapSrc->SurfObj,
                                DCDest->rosdc.CombinedClip,
@@ -135,7 +133,7 @@ NtGdiAlphaBlend(
 
     EXLATEOBJ_vCleanup(&exlo);
 leave :
-    DPRINT("Finishing blit\n");
+    TRACE("Finishing blit\n");
     DC_vFinishBlit(DCDest, DCSrc);
     GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
     GDIOBJ_vUnlockObject(&DCDest->BaseObject);
@@ -197,12 +195,12 @@ NtGdiTransparentBlt(
     BOOL Ret = FALSE;
     EXLATEOBJ exlo;
 
-    DPRINT("Locking DCs\n");
+    TRACE("Locking DCs\n");
     ahDC[0] = hdcDst;
     ahDC[1] = hdcSrc ;
     if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
     {
-        DPRINT1("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc);
+        WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc);
         EngSetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
@@ -343,7 +341,7 @@ NtGdiMaskBlt(
     }
     else if(psurfMask)
     {
-        DPRINT1("Getting Mask bitmap without needing it?\n");
+        WARN("Getting Mask bitmap without needing it?\n");
         SURFACE_ShareUnlockSurface(psurfMask);
         psurfMask = NULL;
     }
@@ -351,12 +349,12 @@ NtGdiMaskBlt(
     MaskPoint.y = yMask;
 
     /* Take care of source and destination bitmap */
-    DPRINT("Locking DCs\n");
+    TRACE("Locking DCs\n");
     ahDC[0] = hdcDest;
     ahDC[1] = UsesSource ? hdcSrc : NULL;
     if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
     {
-        DPRINT1("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDest, hdcSrc);
+        WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDest, hdcSrc);
         EngSetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
@@ -367,7 +365,7 @@ NtGdiMaskBlt(
     if (NULL == DCDest)
     {
         if(DCSrc) DC_UnlockDc(DCSrc);
-        DPRINT("Invalid destination dc handle (0x%p) passed to NtGdiBitBlt\n", hdcDest);
+        WARN("Invalid destination dc handle (0x%p) passed to NtGdiBitBlt\n", hdcDest);
         return FALSE;
     }
 
@@ -497,7 +495,7 @@ NtGdiPlgBlt(
     IN INT yMask,
     IN DWORD crBackColor)
 {
-    UNIMPLEMENTED;
+    FIXME("NtGdiPlgBlt: unimplemented.\n");
     return FALSE;
 }
 
@@ -558,7 +556,7 @@ GreStretchBltMask(
     ahDC[2] = UsesMask ? hDCMask : NULL;
     if (!GDIOBJ_bLockMultipleObjects(3, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
     {
-        DPRINT1("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
+        WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to GreStretchBltMask\n", hDCDest, hDCSrc);
         EngSetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
@@ -651,7 +649,7 @@ GreStretchBltMask(
             (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
              BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
         {
-            DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
+            WARN("%dx%d mask is smaller than %dx%d bitmap\n",
                     BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
                     WidthSrc, HeightSrc);
             EXLATEOBJ_vCleanup(&exlo);
@@ -853,7 +851,7 @@ IntGdiPolyPatBlt(
         if (pbrush != NULL)
         {
             /* Initialize a brush object */
-            EBRUSHOBJ_vInit(&eboFill, pbrush, pdc);
+            EBRUSHOBJ_vInitFromDC(&eboFill, pbrush, pdc);
 
             IntPatBlt(
                 pdc,
index 78d5a10..69288ae 100644 (file)
@@ -98,6 +98,8 @@ BOOL NTAPI BRUSH_Cleanup(PVOID ObjectBody);
 
 extern HSURF gahsurfHatch[HS_DDI_MAX];
 
+struct _SURFACE;
+struct _PALETTE;
 struct _DC;
 
 INIT_FUNCTION
@@ -107,7 +109,11 @@ InitBrushImpl(VOID);
 
 VOID
 NTAPI
-EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _DC *);
+EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _SURFACE *, COLORREF, COLORREF, struct _PALETTE *);
+
+VOID
+NTAPI
+EBRUSHOBJ_vInitFromDC(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _DC *);
 
 VOID
 FASTCALL
@@ -115,7 +121,7 @@ EBRUSHOBJ_vSetSolidRGBColor(EBRUSHOBJ *pebo, COLORREF crColor);
 
 VOID
 NTAPI
-EBRUSHOBJ_vUpdate(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _DC *pdc);
+EBRUSHOBJ_vUpdateFromDC(EBRUSHOBJ *pebo, PBRUSH pbrush, struct _DC *);
 
 BOOL
 NTAPI
index 261cb16..66c709b 100644 (file)
@@ -270,10 +270,10 @@ DC_vInitDc(
        pdc->dcattr.ptlBrushOrigin = pdc->dclevel.ptlBrushOrigin;
 
     /* Initialize EBRUSHOBJs */
-    EBRUSHOBJ_vInit(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
-    EBRUSHOBJ_vInit(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
-    EBRUSHOBJ_vInit(&pdc->eboText, pbrDefaultBrush, pdc);
-    EBRUSHOBJ_vInit(&pdc->eboBackground, pbrDefaultBrush, pdc);
+    EBRUSHOBJ_vInitFromDC(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
+    EBRUSHOBJ_vInitFromDC(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
+    EBRUSHOBJ_vInitFromDC(&pdc->eboText, pbrDefaultBrush, pdc);
+    EBRUSHOBJ_vInitFromDC(&pdc->eboBackground, pbrDefaultBrush, pdc);
 
     /* Setup fill data */
        pdc->dcattr.jROP2 = R2_COPYPEN;
index 370953f..db9bdbc 100644 (file)
@@ -43,7 +43,7 @@ DC_vUpdateFillBrush(PDC pdc)
     if (pdcattr->ulDirty_ & DIRTY_FILL)
     {
         /* Update eboFill */
-        EBRUSHOBJ_vUpdate(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
+        EBRUSHOBJ_vUpdateFromDC(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
     }
 
     /* Check for DC brush */
@@ -90,7 +90,7 @@ DC_vUpdateLineBrush(PDC pdc)
     if (pdcattr->ulDirty_ & DIRTY_LINE)
     {
         /* Update eboLine */
-        EBRUSHOBJ_vUpdate(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
+        EBRUSHOBJ_vUpdateFromDC(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
     }
 
     /* Check for DC pen */
@@ -113,7 +113,7 @@ DC_vUpdateTextBrush(PDC pdc)
     /* Timo : The text brush should never be changed.
      * Jérôme : Yeah, but its palette must be updated anyway! */
     if(pdcattr->ulDirty_ & DIRTY_TEXT)
-        EBRUSHOBJ_vUpdate(&pdc->eboText, pbrDefaultBrush, pdc);
+        EBRUSHOBJ_vUpdateFromDC(&pdc->eboText, pbrDefaultBrush, pdc);
 
     /* Update the eboText's solid color */
     EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboText, pdcattr->crForegroundClr);
@@ -129,7 +129,7 @@ DC_vUpdateBackgroundBrush(PDC pdc)
     PDC_ATTR pdcattr = pdc->pdcattr;
 
     if(pdcattr->ulDirty_ & DIRTY_BACKGROUND)
-        EBRUSHOBJ_vUpdate(&pdc->eboBackground, pbrDefaultBrush, pdc);
+        EBRUSHOBJ_vUpdateFromDC(&pdc->eboBackground, pbrDefaultBrush, pdc);
 
     /* Update the eboBackground's solid color */
     EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboBackground, pdcattr->crBackgroundClr);
index 91f4166..4be2e64 100644 (file)
@@ -1042,7 +1042,14 @@ CLEANUP:
 }
 #endif
 
-/* Mostly inspired from wine code */
+/* Mostly inspired from wine code.
+ * We use low level functions because:
+ *  - at this point, the icon bitmap could have a different bit depth than the DC,
+ *    making it thus impossible to use NtCreateCompatibleDC and selecting the bitmap.
+ *    This happens after a mode setting change.
+ *  - it avoids massive GDI objects locking when only the destination surface needs it.
+ *  - It makes (small) performance gains.
+ */
 BOOL
 UserDrawIconEx(
     HDC hDc,
@@ -1055,128 +1062,220 @@ UserDrawIconEx(
     HBRUSH hbrFlickerFreeDraw,
     UINT diFlags)
 {
+    PSURFACE psurfDest, psurfMask, psurfColor, psurfOffScreen;
+    PDC pdc = NULL;
     BOOL Ret = FALSE;
     HBITMAP hbmMask, hbmColor;
-    BITMAP bmpColor, bm;
-    BOOL DoFlickerFree;
-    INT iOldBkColor = 0, iOldTxtColor = 0;
-
-    HDC hMemDC, hDestDC = hDc;
-    HGDIOBJ hOldOffBrush = 0;
-    HGDIOBJ hOldOffBmp = 0;
-    HBITMAP hTmpBmp = 0, hOffBmp = 0;
-    BOOL bAlpha = FALSE;
-    INT x=xLeft, y=yTop;
+    BOOL bOffScreen, bAlpha = FALSE;
+    RECTL rcDest, rcSrc;
+    CLIPOBJ* pdcClipObj = NULL;
+    EXLATEOBJ exlo;
+    
+    /* Stupid case */
+    if((diFlags & DI_NORMAL) == 0)
+    {
+        ERR("DrawIconEx called without mask or color bitmap to draw.\n");
+        return FALSE;
+    }
 
     hbmMask = pIcon->IconInfo.hbmMask;
     hbmColor = pIcon->IconInfo.hbmColor;
-
+    
     if (istepIfAniCur)
         ERR("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
-
-    if (!hbmMask || !GreGetObject(hbmMask, sizeof(BITMAP), (PVOID)&bm))
-    {
+    
+    /*
+     * Get our objects. 
+     * Shared locks are enough, we are only reading those bitmaps
+     */
+    psurfMask = SURFACE_ShareLockSurface(hbmMask);
+    if(psurfMask == NULL)
+    {
+        ERR("Unable to lock the mask surface.\n");
         return FALSE;
     }
-
-    if (hbmColor && !GreGetObject(hbmColor, sizeof(BITMAP), (PVOID)&bmpColor))
+    
+    /* Color bitmap is not mandatory */
+    if(hbmColor == NULL)
     {
-        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");
@@ -1197,109 +1296,181 @@ UserDrawIconEx(
                                ptr += 4;
             }
         }
-
-        SURFACE_ShareUnlockSurface(psurf);
-
-        hTmpBmp = NtGdiSelectBitmap(hMemDC, hMemBmp);
-
-        Ret = NtGdiAlphaBlend(hDestDC,
-                                                 x,
-                                                     y,
-                              cxWidth,
-                              cyHeight,
-                              hMemDC,
-                              0,
-                              0,
-                              pIcon->Size.cx,
-                              pIcon->Size.cy,
-                              pixelblend,
-                              NULL);
-        NtGdiSelectBitmap(hMemDC, hTmpBmp);
+        
+        /* Initialize color translation object */
+        EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+        
+        /* Now do it */
+        Ret = IntEngAlphaBlend(&psurfDest->SurfObj,
+                               &psurf->SurfObj,
+                               pdcClipObj,
+                               &exlo.xlo,
+                               &rcDest,
+                               &rcSrc,
+                               &blendobj);
+        
+        EXLATEOBJ_vCleanup(&exlo);
+        
     CleanupAlpha:
-        if(hMemBmp) NtGdiDeleteObjectApp(hMemBmp);
+        if(psurf) SURFACE_ShareUnlockSurface(psurf);
+        if(hsurfCopy) NtGdiDeleteObjectApp(hsurfCopy);
                if(Ret) goto done;
+               ERR("NtGdiAlphaBlend failed!\n");
     }
 
     if (diFlags & DI_MASK)
     {
-        DWORD rop = (diFlags & DI_IMAGE) ? SRCAND : SRCCOPY;
-        hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
-        NtGdiStretchBlt(hDestDC,
-                        x,
-                        y,
-                        cxWidth,
-                        cyHeight,
-                        hMemDC,
-                        0,
-                        0,
-                        pIcon->Size.cx,
-                        pIcon->Size.cy,
-                        rop,
-                        0);
-        NtGdiSelectBitmap(hMemDC, hTmpBmp);
+        DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY;
+        
+        EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0);
+        
+        Ret = IntEngStretchBlt(&psurfDest->SurfObj,
+                               &psurfMask->SurfObj,
+                               NULL,
+                               pdcClipObj,
+                               &exlo.xlo,
+                               NULL,
+                               &rcDest,
+                               &rcSrc,
+                               NULL,
+                               NULL,
+                               NULL,
+                               rop4);
+        
+        EXLATEOBJ_vCleanup(&exlo);
+
+        if(!Ret)
+        {
+            ERR("Failed to mask the bitmap data.\n");
+            goto Cleanup;
+        }
     }
 
     if(diFlags & DI_IMAGE)
     {
-               if (hbmColor)
+               if (psurfColor)
         {
-            DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
-            hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmColor);
-            NtGdiStretchBlt(hDestDC,
-                            x,
-                            y,
-                            cxWidth,
-                            cyHeight,
-                            hMemDC,
-                            0,
-                            0,
-                            pIcon->Size.cx,
-                            pIcon->Size.cy,
-                            rop,
-                            0);
-            NtGdiSelectBitmap(hMemDC, hTmpBmp);
+            DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY ;
+            
+            EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0);
+            
+            Ret = IntEngStretchBlt(&psurfDest->SurfObj,
+                                   &psurfColor->SurfObj,
+                                   NULL,
+                                   pdcClipObj,
+                                   &exlo.xlo,
+                                   NULL,
+                                   &rcDest,
+                                   &rcSrc,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   rop4);
+        
+            EXLATEOBJ_vCleanup(&exlo);
+
+            if(!Ret)
+            {
+                ERR("Failed to render the icon bitmap.\n");
+                goto Cleanup;
+            }
         }
         else
         {
-            /* Mask bitmap holds the information in its second half */
-            DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
-            hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
-            NtGdiStretchBlt(hDestDC,
-                            x,
-                            y,
-                            cxWidth,
-                            cyHeight,
-                            hMemDC,
-                            0,
-                            pIcon->Size.cy,
-                            pIcon->Size.cx,
-                            pIcon->Size.cy,
-                            rop,
-                            0);
-            NtGdiSelectBitmap(hMemDC, hTmpBmp);
+            /* Mask bitmap holds the information in its bottom half */
+            DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY;
+            RECTL_vOffsetRect(&rcSrc, 0, pIcon->Size.cy);
+            
+            EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0);
+        
+            Ret = IntEngStretchBlt(&psurfDest->SurfObj,
+                                   &psurfMask->SurfObj,
+                                   NULL,
+                                   pdcClipObj,
+                                   &exlo.xlo,
+                                   NULL,
+                                   &rcDest,
+                                   &rcSrc,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   rop4);
+            
+            EXLATEOBJ_vCleanup(&exlo);
+
+            if(!Ret)
+            {
+                ERR("Failed to render the icon bitmap.\n");
+                goto Cleanup;
+            }
         }
     }
 
 done:
-    if(hDestDC != hDc)
+    /* We're done. Was it a double buffered draw ? */
+    if(bOffScreen)
     {
-        NtGdiBitBlt(hDc, xLeft, yTop, cxWidth, cyHeight, hDestDC, 0, 0, SRCCOPY, 0, 0);
+        /* Yes. Draw it back to our DC */
+        POINTL ptSrc = {0, 0};
+        pdc = DC_LockDc(hDc);
+        if(!pdc)
+        {
+            ERR("Could not lock the destination DC.\n");
+            return FALSE;
+        }
+        /* Calculate destination rectangle */
+        RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight);
+        IntLPtoDP(pdc, (LPPOINT)&rcDest, 2);
+        RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
+        
+        /* Prepare the underlying surface */
+        DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest);
+        
+        /* Get the clip object */
+        pdcClipObj = pdc->rosdc.CombinedClip;
+        
+        /* We now have our destination surface and rectangle */
+        psurfDest = pdc->dclevel.pSurface;
+        if(!psurfDest)
+        {
+            /* So, you did all of this for an empty DC. */
+            DC_UnlockDc(pdc);
+            goto Cleanup2;
+        }
+        
+        /* Color translation */
+        EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0);
+        
+        /* Blt it! */
+        Ret = IntEngBitBlt(&psurfDest->SurfObj,
+                           &psurfOffScreen->SurfObj,
+                           NULL,
+                           pdcClipObj,
+                           &exlo.xlo,
+                           &rcDest,
+                           &ptSrc,
+                           NULL,
+                           NULL,
+                           NULL,
+                           ROP4_SRCCOPY);
+                           
+        EXLATEOBJ_vCleanup(&exlo);
     }
-
-    /* Restore foreground and background colors */
-    IntGdiSetBkColor(hDc, iOldBkColor);
-    IntGdiSetTextColor(hDc, iOldTxtColor);
-
-    Ret = TRUE ;
-
 Cleanup:
-    NtGdiDeleteObjectApp(hMemDC);
-    if(hDestDC != hDc)
-    {
-        if(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;
 }