* Sync up to trunk head (r65298).
authorAmine Khaldi <amine.khaldi@reactos.org>
Thu, 6 Nov 2014 19:24:18 +0000 (19:24 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Thu, 6 Nov 2014 19:24:18 +0000 (19:24 +0000)
svn path=/branches/shell-experiments/; revision=65299

12 files changed:
drivers/filesystems/fastfat/create.c
drivers/filesystems/fastfat/direntry.c
drivers/filesystems/fastfat/dirwr.c
drivers/filesystems/fastfat/fcb.c
lib/fast486/common.c
lib/fast486/common.inl
lib/fast486/extraops.c
lib/fast486/opcodes.c
lib/fast486/opgroups.c
ntoskrnl/io/iomgr/file.c
win32ss/gdi/ntgdi/fillshap.c
win32ss/user/user32/misc/exticon.c

index 32b372e..ede9a75 100644 (file)
@@ -565,11 +565,14 @@ VfatCreateFile(
         LONG idx, FileNameLen;
 
         ParentFcb = (FileObject->RelatedFileObject != NULL) ? FileObject->RelatedFileObject->FsContext : NULL;
+        if (ParentFcb)
+        {
+            vfatGrabFCB(DeviceExt, ParentFcb);
+        }
         Status = vfatGetFCBForFile(DeviceExt, &ParentFcb, &TargetFcb, &PathNameU);
 
-        if (Status == STATUS_SUCCESS)
+        if (NT_SUCCESS(Status))
         {
-            vfatGrabFCB(DeviceExt, ParentFcb);
             vfatReleaseFCB(DeviceExt, TargetFcb);
             Irp->IoStatus.Information = FILE_EXISTS;
         }
@@ -580,7 +583,7 @@ VfatCreateFile(
 
         idx = FileObject->FileName.Length / sizeof(WCHAR) - 1;
 
-        /* Skip tailing \ - if any */
+        /* Skip trailing \ - if any */
         if (PathNameU.Buffer[idx] == L'\\')
         {
             --idx;
@@ -623,6 +626,7 @@ VfatCreateFile(
         if (NT_SUCCESS(Status))
         {
             pFcb = FileObject->FsContext;
+            ASSERT(pFcb == ParentFcb);
 
             if (pFcb->OpenHandleCount == 0)
             {
@@ -640,7 +644,6 @@ VfatCreateFile(
                                             FALSE);
                 if (!NT_SUCCESS(Status))
                 {
-                    vfatReleaseFCB(DeviceExt, ParentFcb);
                     VfatCloseFile(DeviceExt, FileObject);
                     return Status;
                 }
index f3dc5b9..336f014 100644 (file)
@@ -201,12 +201,6 @@ FATGetNextDirEntry(
             CcUnpinData(*pContext);
         }
 
-        if (!pDirFcb->FileObject)
-        {
-            DPRINT1("Buggy FCB (cleaned up)! %S (%d / %u)\n", pDirFcb->PathNameBuffer, pDirFcb->RefCount, pDirFcb->OpenHandleCount);
-            return STATUS_NO_MORE_ENTRIES;
-        }
-
         if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
             !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
         {
index e9622a8..21b0e69 100644 (file)
@@ -167,11 +167,6 @@ vfatFindDirSpace(
             {
                 CcUnpinData(Context);
             }
-            if (!pDirFcb->FileObject)
-            {
-                DPRINT1("Buggy FCB (cleaned up)! %S (%d / %u)\n", pDirFcb->PathNameBuffer, pDirFcb->RefCount, pDirFcb->OpenHandleCount);
-                return FALSE;
-            }
             if (!CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster,
                       TRUE, &Context, (PVOID*)&pFatEntry))
             {
index f2a04e7..df4dd54 100644 (file)
@@ -371,6 +371,13 @@ vfatUpdateFCB(
 
     DPRINT("vfatUpdateFCB(%p, %p, %wZ, %wZ, %p)\n", pVCB, Fcb, LongName, ShortName, ParentFcb);
 
+    /* Get full path name */
+    Status = vfatMakeFullName(ParentFcb, LongName, ShortName, &Fcb->PathNameU);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
     /* Delete old name */
     if (Fcb->PathNameBuffer)
     {
@@ -380,13 +387,6 @@ vfatUpdateFCB(
     /* Delete from table */
     vfatDelFCBFromTable(pVCB, Fcb);
 
-    /* Get full path name */
-    Status = vfatMakeFullName(ParentFcb, LongName, ShortName, &Fcb->PathNameU);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
     /* Split it properly */
     Fcb->PathNameBuffer = Fcb->PathNameU.Buffer;
     Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
@@ -414,8 +414,8 @@ vfatUpdateFCB(
     /* Add to the table */
     vfatAddFCBToTable(pVCB, Fcb);
 
-    /* If we moved accross directories, dereferenced our old parent
-     * We also derefence in case we're just renaming since AddFCBToTable references it
+    /* If we moved across directories, dereference our old parent
+     * We also dereference in case we're just renaming since AddFCBToTable references it
      */
     vfatReleaseFCB(pVCB, OldParent);
 
@@ -887,7 +887,7 @@ vfatGetFCBForFile(
         if (parentFCB)
         {
             vfatReleaseFCB(pVCB, parentFCB);
-            parentFCB = 0;
+            parentFCB = NULL;
         }
         //  fail if element in FCB is not a directory
         if (!vfatFCBIsDirectory(FCB))
@@ -910,6 +910,8 @@ vfatGetFCBForFile(
                 if (FileNameU.Length + parentFCB->LongNameU.Length - Length > FileNameU.MaximumLength)
                 {
                     vfatReleaseFCB(pVCB, parentFCB);
+                    *pParentFCB = NULL;
+                    *pFCB = NULL;
                     return STATUS_OBJECT_NAME_INVALID;
                 }
                 RtlMoveMemory(prev + parentFCB->LongNameU.Length / sizeof(WCHAR), curr,
index 61a120b..a16b591 100644 (file)
@@ -106,6 +106,13 @@ Fast486ReadMemory(PFAST486_STATE State,
             /* We mustn't prefetch across a page boundary */
             State->PrefetchAddress = PAGE_ALIGN(State->PrefetchAddress)
                                      | (FAST486_PAGE_SIZE - FAST486_CACHE_SIZE);
+
+            if ((LinearAddress - State->PrefetchAddress + Size) >= FAST486_CACHE_SIZE)
+            {
+                /* We can't prefetch without possibly violating page permissions */
+                State->PrefetchValid = FALSE;
+                return Fast486ReadLinearMemory(State, LinearAddress, Buffer, Size);
+            }
         }
 
         /* Prefetch */
@@ -546,7 +553,12 @@ Fast486TaskSwitch(PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Se
 
     /* Calculate the limit of the new TSS */
     NewTssLimit = NewTssDescriptor.Limit | (NewTssDescriptor.LimitHigh << 16);
-    if (NewTssDescriptor.Granularity) NewTssLimit <<= 12;
+
+    if (NewTssDescriptor.Granularity)
+    {
+        NewTssLimit <<= 12;
+        NewTssLimit |= 0x00000FFF;
+    }
 
     if (NewTssLimit < sizeof(FAST486_TSS))
     {
@@ -732,7 +744,12 @@ Fast486TaskSwitch(PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Se
         State->Ldtr.Selector = NewTss.Ldtr;
         State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
         State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
-        if (GdtEntry.Granularity) State->Ldtr.Limit <<= 12;
+
+        if (GdtEntry.Granularity)
+        {
+            State->Ldtr.Limit <<= 12;
+            State->Ldtr.Limit |= 0x00000FFF;
+        }
     }
     else
     {
index 6828583..73bb537 100644 (file)
@@ -594,16 +594,12 @@ Fast486LoadSegmentInternal(PFAST486_STATE State,
             {
                 /* Regular code segment */
 
-                if ((GET_SEGMENT_RPL(Selector) > Fast486GetCurrentPrivLevel(State))
-                    || (Fast486GetCurrentPrivLevel(State) != GdtEntry.Dpl))
+                if ((GET_SEGMENT_RPL(Selector) < Fast486GetCurrentPrivLevel(State)))
                 {
                     Fast486ExceptionWithErrorCode(State, Exception, Selector);
                     return FALSE;
                 }
             }
-
-            /* Update CPL */
-            State->Cpl = GET_SEGMENT_RPL(Selector);
         }
         else
         {
@@ -653,7 +649,11 @@ Fast486LoadSegmentInternal(PFAST486_STATE State,
         CachedDescriptor->Size = GdtEntry.Size;
 
         /* Check for page granularity */
-        if (GdtEntry.Granularity) CachedDescriptor->Limit <<= 12;
+        if (GdtEntry.Granularity)
+        {
+            CachedDescriptor->Limit <<= 12;
+            CachedDescriptor->Limit |= 0x00000FFF;
+        }
     }
     else
     {
@@ -730,6 +730,13 @@ Fast486ProcessGate(PFAST486_STATE State, USHORT Selector, ULONG Offset, BOOLEAN
 
         default:
         {
+            /* Security check for jumps and calls only */
+            if (State->Cpl != Descriptor.Dpl)
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
             return TRUE;
         }
     }
index 6a73fb8..1f2fc72 100644 (file)
@@ -475,7 +475,12 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLsl)
 
     /* Calculate the limit */
     Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
-    if (GdtEntry.Granularity) Limit <<= 12;
+
+    if (GdtEntry.Granularity)
+    {
+        Limit <<= 12;
+        Limit |= 0x00000FFF;
+    }
 
     /* Set ZF */
     State->Flags.Zf = TRUE;
index 0e004ea..e8a6a25 100644 (file)
@@ -4474,6 +4474,63 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeRetFar)
         return;
     }
 
+    if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
+    {
+        INT i;
+        INT OldCpl = Fast486GetCurrentPrivLevel(State);
+        ULONG StackPtr;
+        ULONG StackSel;
+        
+        if (GET_SEGMENT_RPL(Segment) > OldCpl)
+        {
+            /* Pop ESP */
+            if (!Fast486StackPop(State, &StackPtr))
+            {
+                /* Exception */
+                return;
+            }
+
+            /* Pop SS */
+            if (!Fast486StackPop(State, &StackSel))
+            {
+                /* Exception */
+                return;
+            }
+        }
+
+        /* Update the CPL */
+        State->Cpl = GET_SEGMENT_RPL(Segment);
+
+        if (State->Cpl > OldCpl)
+        {
+            /* Load new SS */
+            if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel))
+            {
+                /* Exception */
+                return;
+            }
+
+            /* Set ESP */
+            if (Size) State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr;
+            else State->GeneralRegs[FAST486_REG_ESP].LowWord = LOWORD(StackPtr);
+
+            /* Check segment security */
+            for (i = 0; i < FAST486_NUM_SEG_REGS; i++)
+            {
+                /* Don't check CS or SS */
+                if ((i == FAST486_REG_CS) || (i == FAST486_REG_SS)) continue;
+
+                if ((State->Cpl > State->SegmentRegs[i].Dpl)
+                    && (!State->SegmentRegs[i].Executable
+                    || !State->SegmentRegs[i].DirConf))
+                {
+                    /* Load the NULL descriptor in the segment */
+                    if (!Fast486LoadSegment(State, i, 0)) return;
+                }
+            }
+        }
+    }
+
     /* Load new (E)IP, and if necessary, pop the parameters */
     if (Size)
     {
@@ -4582,7 +4639,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
     /* Check for protected mode */
     if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
     {
-        INT Cpl = Fast486GetCurrentPrivLevel(State);
+        INT OldCpl = Fast486GetCurrentPrivLevel(State);
 
         if (State->Flags.Vm)
         {
@@ -4660,7 +4717,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
         if (Size) State->InstPtr.Long = InstPtr;
         else State->InstPtr.LowWord = LOWORD(InstPtr);
 
-        if (GET_SEGMENT_RPL(CodeSel) > Cpl)
+        if (GET_SEGMENT_RPL(CodeSel) > OldCpl)
         {
             /* Pop ESP */
             if (!Fast486StackPop(State, &StackPtr))
@@ -4675,7 +4732,22 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
                 /* Exception */
                 return;
             }
+        }
+
+        /* Update the CPL */
+        State->Cpl = GET_SEGMENT_RPL(CodeSel);
 
+        /* Set the new flags */
+        if (Size) State->Flags.Long = NewFlags.Long & PROT_MODE_FLAGS_MASK;
+        else State->Flags.LowWord = NewFlags.LowWord & PROT_MODE_FLAGS_MASK;
+        State->Flags.AlwaysSet = TRUE;
+
+        /* Set additional flags */
+        if (OldCpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
+        if (OldCpl == 0) State->Flags.Iopl = NewFlags.Iopl;
+
+        if (State->Cpl > OldCpl)
+        {
             /* Load new SS */
             if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel))
             {
@@ -4686,21 +4758,6 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
             /* Set ESP */
             if (Size) State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr;
             else State->GeneralRegs[FAST486_REG_ESP].LowWord = LOWORD(StackPtr);
-        }
-
-        /* Set the new flags */
-        if (Size) State->Flags.Long = NewFlags.Long & PROT_MODE_FLAGS_MASK;
-        else State->Flags.LowWord = NewFlags.LowWord & PROT_MODE_FLAGS_MASK;
-        State->Flags.AlwaysSet = TRUE;
-
-        /* Set additional flags */
-        if (Cpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
-        if (Cpl == 0) State->Flags.Iopl = NewFlags.Iopl;
-
-        if (GET_SEGMENT_RPL(CodeSel) > Cpl)
-        {
-            /* Update the CPL */
-            Cpl = Fast486GetCurrentPrivLevel(State);
 
             /* Check segment security */
             for (i = 0; i < FAST486_NUM_SEG_REGS; i++)
@@ -4708,7 +4765,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
                 /* Don't check CS or SS */
                 if ((i == FAST486_REG_CS) || (i == FAST486_REG_SS)) continue;
 
-                if ((Cpl > State->SegmentRegs[i].Dpl)
+                if ((State->Cpl > State->SegmentRegs[i].Dpl)
                     && (!State->SegmentRegs[i].Executable
                     || !State->SegmentRegs[i].DirConf))
                 {
index 95a99cc..3f5e828 100644 (file)
@@ -1804,7 +1804,12 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
             State->Ldtr.Selector = Selector;
             State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
             State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
-            if (GdtEntry.Granularity) State->Ldtr.Limit <<= 12;
+
+            if (GdtEntry.Granularity)
+            {
+                State->Ldtr.Limit <<= 12;
+                State->Ldtr.Limit |= 0x00000FFF;
+            }
 
             break;
         }
@@ -1886,7 +1891,12 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
             State->TaskReg.Selector = Selector;
             State->TaskReg.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
             State->TaskReg.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
-            if (GdtEntry.Granularity) State->TaskReg.Limit <<= 12;
+
+            if (GdtEntry.Granularity)
+            {
+                State->TaskReg.Limit <<= 12;
+                State->TaskReg.Limit |= 0x00000FFF;
+            }
 
             break;
         }
index bcb3fbb..6b454d9 100644 (file)
@@ -1580,8 +1580,8 @@ IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
     if (OpenPacket.ParseCheck != TRUE)
     {
         /* Parse failed */
-        DPRINT1("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n",
-                ObjectAttributes->ObjectName, Status);
+        DPRINT("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n",
+               ObjectAttributes->ObjectName, Status);
         return Status;
     }
     else
index 0d323c3..1c72756 100644 (file)
@@ -1132,7 +1132,7 @@ NtGdiExtFloodFill(
             goto cleanup;
     }
     else
-        RECTL_vSetRect(&DestRect, 0, psurf->SurfObj.sizlBitmap.cx, 0, psurf->SurfObj.sizlBitmap.cy);
+        RECTL_vSetRect(&DestRect, 0, 0, psurf->SurfObj.sizlBitmap.cx, psurf->SurfObj.sizlBitmap.cy);
 
     DC_vPrepareDCsForBlit(dc, &DestRect, NULL, NULL);
 
index 7455f22..ddc683e 100644 (file)
@@ -112,7 +112,7 @@ static DWORD USER32_GetResourceTable(LPBYTE peimage,DWORD pesize,LPBYTE *retptr)
        }
        if (*((DWORD*)(peimage + mz_header->e_lfanew)) == IMAGE_NT_SIGNATURE )
          return IMAGE_NT_SIGNATURE;
-#if 0
+#ifdef WINE
        if (*((WORD*)(peimage + mz_header->e_lfanew)) == IMAGE_OS2_SIGNATURE )
        {
          IMAGE_OS2_HEADER      * ne_header;
@@ -132,7 +132,7 @@ static DWORD USER32_GetResourceTable(LPBYTE peimage,DWORD pesize,LPBYTE *retptr)
 #endif
        return 0; /* failed */
 }
-#if 0
+#ifdef WINE
 /*************************************************************************
  *                     USER32_LoadResource
  */
@@ -160,9 +160,6 @@ static BYTE * ICO_LoadIcon( LPBYTE peimage, LPicoICONDIRENTRY lpiIDE, ULONG *uSi
  *
  * Reads .ico file and build phony ICONDIR struct
  */
-#define HEADER_SIZE            (sizeof(CURSORICONDIR) - sizeof (CURSORICONDIRENTRY))
-#define HEADER_SIZE_FILE       (sizeof(icoICONDIR) - sizeof (icoICONDIRENTRY))
-
 static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG *uSize )
 {
        CURSORICONDIR   * lpcid;        /* icon resource in resource-dir format */
@@ -177,7 +174,7 @@ static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG
          return 0;
 
        /* allocate the phony ICONDIR structure */
-       *uSize = lpcid->idCount * sizeof(CURSORICONDIRENTRY) + HEADER_SIZE;
+        *uSize = FIELD_OFFSET(CURSORICONDIR, idEntries[lpcid->idCount]);
        if( (lpID = HeapAlloc(GetProcessHeap(),0, *uSize) ))
        {
          /* copy the header */
@@ -188,7 +185,7 @@ static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG
          /* copy the entries */
          for( i=0; i < lpcid->idCount; i++ )
          {
-           memcpy(&lpID->idEntries[i], &lpcid->idEntries[i], sizeof(CURSORICONDIRENTRY) - 2);
+            memcpy(&lpID->idEntries[i], &lpcid->idEntries[i], sizeof(CURSORICONDIRENTRY) - 2);
            lpID->idEntries[i].wResId = i;
          }
 
@@ -224,7 +221,7 @@ static UINT ICO_ExtractIconExW(
        LPBYTE          pData;
        DWORD           sig;
        HANDLE          hFile;
-       UINT16          iconDirCount = 0; //,iconCount = 0;
+       UINT16          iconDirCount = 0iconCount = 0;
        LPBYTE          peimage;
        HANDLE          fmapping;
        DWORD           fsizeh,fsizel;
@@ -274,8 +271,8 @@ static UINT ICO_ExtractIconExW(
 
        sig = USER32_GetResourceTable(peimage, fsizel, &pData);
 
+#ifdef WINE
 /* ico file or NE exe/dll*/
-#if 0
        if (sig==IMAGE_OS2_SIGNATURE || sig==1) /* .ICO file */
        {
          BYTE          *pCIDir = 0;
@@ -283,8 +280,9 @@ static UINT ICO_ExtractIconExW(
          NE_NAMEINFO   *pIconStorage = NULL;
          NE_NAMEINFO   *pIconDir = NULL;
          LPicoICONDIR  lpiID = NULL;
+         ULONG         uSize = 0;
 
-         TRACE("-- OS2/icon Signature (0x%08lx)\n", sig);
+          TRACE("-- OS2/icon Signature (0x%08x)\n", sig);
 
          if (pData == (BYTE*)-1)
          {
@@ -292,7 +290,7 @@ static UINT ICO_ExtractIconExW(
            if (pCIDir)
            {
              iconDirCount = 1; iconCount = lpiID->idCount;
-             TRACE("-- icon found %p 0x%08lx 0x%08x 0x%08x\n", pCIDir, uSize, iconDirCount, iconCount);
+              TRACE("-- icon found %p 0x%08x 0x%08x 0x%08x\n", pCIDir, uSize, iconDirCount, iconCount);
            }
          }
          else while (pTInfo->type_id && !(pIconStorage && pIconDir))
@@ -317,7 +315,7 @@ static UINT ICO_ExtractIconExW(
            if (nIcons == 0)
            {
              ret = iconDirCount;
-             if (lpiID && pCIDir)      /* *.ico file, deallocate heap pointer*/
+              if (lpiID)       /* *.ico file, deallocate heap pointer*/
                HeapFree(GetProcessHeap(), 0, pCIDir);
            }
            else if (nIconIndex < iconDirCount)
@@ -331,9 +329,10 @@ static UINT ICO_ExtractIconExW(
                /* .ICO files have only one icon directory */
                if (lpiID == NULL)      /* not *.ico */
                  pCIDir = USER32_LoadResource(peimage, pIconDir + i + nIconIndex, *(WORD*)pData, &uSize);
-               pIconId[i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, (i & 1) ? cx2 : cx1, (i & 1) ? cy2 : cy1, flags);
+               pIconId[i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, cx1, cy1, flags);
+                if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE,  cx2, cy2, flags);
              }
-             if (lpiID && pCIDir)      /* *.ico file, deallocate heap pointer*/
+              if (lpiID)       /* *.ico file, deallocate heap pointer*/
                HeapFree(GetProcessHeap(), 0, pCIDir);
 
              for (icon = 0; icon < nIcons; icon++)
@@ -347,8 +346,13 @@ static UINT ICO_ExtractIconExW(
                      pCIDir = USER32_LoadResource(peimage, pIconStorage + i, *(WORD*)pData, &uSize);
 
                if (pCIDir)
-                 RetPtr[icon] = (HICON)CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000,
-                                                                (icon & 1) ? cx2 : cx1, (icon & 1) ? cy2 : cy1, flags);
+                {
+                 RetPtr[icon] = CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000,
+                                                                 cx1, cy1, flags);
+                  if (cx2 && cy2)
+                      RetPtr[++icon] = CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000,
+                                                                       cx2, cy2, flags);
+                }
                else
                  RetPtr[icon] = 0;
              }
@@ -356,54 +360,62 @@ static UINT ICO_ExtractIconExW(
            }
          }
        }
+#else
+    if (sig == 1) /* .ICO file */
+    {
+        TRACE("-- icon Signature (0x%08x)\n", sig);
+
+        if (pData == (BYTE*)-1)
+        {
+            INT dataOffset;
+            LPICONIMAGE entry;
+            CURSORICONDIR *lpcid = (CURSORICONDIR*)peimage;
+            INT cx[2] = {cx1, cx2}, cy[2] = {cy1, cy2};
+            INT index;
+
+            if (lpcid->idType != 1)
+                return 0;
+
+            for(index = 0; index < 2; index++)
+            {
+                dataOffset = LookupIconIdFromDirectoryEx(peimage, TRUE, cx[index], cy[index], flags);
+
+                if (dataOffset)
+                {
+                    HICON icon;
+                    entry = (LPICONIMAGE)(peimage + dataOffset);
+                    icon = CreateIconFromResourceEx(peimage + dataOffset, entry->icHeader.biSizeImage, TRUE, 0x00030000, cx[index], cy[index], flags);
+
+                    if (icon)
+                    {
+                        RetPtr[index] = icon;
+                        iconCount = 1;
+                    }
+                }
+            }
+
+        }
+        ret = iconCount;       /* return number of retrieved icons */
+    }
+#endif
 /* end ico file */
 
 /* exe/dll */
        else if( sig == IMAGE_NT_SIGNATURE )
-#endif
-       if( sig == IMAGE_NT_SIGNATURE )
        {
-         LPBYTE                idata,igdata;
-         PIMAGE_DOS_HEADER     dheader;
-         PIMAGE_NT_HEADERS     pe_header;
-         PIMAGE_SECTION_HEADER pe_sections;
-         const IMAGE_RESOURCE_DIRECTORY *rootresdir,*iconresdir,*icongroupresdir;
-         const IMAGE_RESOURCE_DATA_ENTRY *idataent,*igdataent;
-         const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
-         UINT  i, j;
-
-         dheader = (PIMAGE_DOS_HEADER)peimage;
-         pe_header = (PIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew);     /* it is a pe header, USER32_GetResourceTable checked that */
-         pe_sections = (PIMAGE_SECTION_HEADER)(((char*)pe_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER)
-                                               + pe_header->FileHeader.SizeOfOptionalHeader);
-         rootresdir = NULL;
-
-         /* search for the root resource directory */
-         for (i=0;i<pe_header->FileHeader.NumberOfSections;i++)
-         {
-           if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
-             continue;
-           if (fsizel < pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData) {
-              FIXME("File %s too short (section is at %ld bytes, real size is %ld)\n",
-                     debugstr_w(lpszExeFileName),
-                     pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData,
-                     fsizel
-             );
-             goto end;
-           }
-           /* FIXME: doesn't work when the resources are not in a separate section */
-           if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress)
-           {
-             rootresdir = (PIMAGE_RESOURCE_DIRECTORY)(peimage+pe_sections[i].PointerToRawData);
-             break;
-           }
-         }
-
-         if (!rootresdir)
-         {
-           WARN("haven't found section for resource directory.\n");
-           goto end;           /* failure */
-         }
+        BYTE *idata, *igdata;
+        const IMAGE_RESOURCE_DIRECTORY *rootresdir, *iconresdir, *icongroupresdir;
+        const IMAGE_RESOURCE_DATA_ENTRY *idataent, *igdataent;
+        const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
+        ULONG size;
+        UINT i;
+
+        rootresdir = RtlImageDirectoryEntryToData((HMODULE)peimage, FALSE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size);
+        if (!rootresdir)
+        {
+            WARN("haven't found section for resource directory.\n");
+            goto end;
+        }
 
          /* search for the group icon directory */
          if (!(icongroupresdir = find_entry_by_id(rootresdir, LOWORD(RT_GROUP_ICON), rootresdir)))
@@ -465,37 +477,21 @@ static UINT ICO_ExtractIconExW(
            const IMAGE_RESOURCE_DIRECTORY *resdir;
 
            /* go down this resource entry, name */
-           resdir = (const IMAGE_RESOURCE_DIRECTORY*)((const char *)rootresdir+(xresent->OffsetToDirectory));
+            resdir = (const IMAGE_RESOURCE_DIRECTORY *)((const char *)rootresdir + xresent->OffsetToDirectory);
 
            /* default language (0) */
            resdir = find_entry_default(resdir,rootresdir);
            igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir;
 
            /* lookup address in mapped image for virtual address */
-           igdata = NULL;
-
-           for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
-           {
-             if (igdataent->OffsetToData < pe_sections[j].VirtualAddress)
-               continue;
-             if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
-               continue;
-
-             if (igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData+igdataent->Size > fsizel) {
-               FIXME("overflow in PE lookup (%s has len %ld, have offset %ld), short file?\n", debugstr_w(lpszExeFileName), fsizel,
-                          igdataent->OffsetToData - pe_sections[j].VirtualAddress + pe_sections[j].PointerToRawData + igdataent->Size);
-               goto end; /* failure */
-             }
-             igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
-           }
-
-           if (!igdata)
+        igdata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, igdataent->OffsetToData, NULL);
+        if (!igdata)
            {
              FIXME("no matching real address for icongroup!\n");
              goto end; /* failure */
            }
            pIconId[i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx1, cy1, flags);
-               if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx2, cy2, flags);
+            if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx2, cy2, flags);
          }
 
          if (!(iconresdir=find_entry_by_id(rootresdir,LOWORD(RT_ICON),rootresdir)))
@@ -508,32 +504,17 @@ static UINT ICO_ExtractIconExW(
          {
            const IMAGE_RESOURCE_DIRECTORY *xresdir;
            xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir);
-           if (!xresdir)
-           {
-             WARN("icon entry %d not found\n", LOWORD(pIconId[i]));
+            if( !xresdir )
+            {
+              WARN("icon entry %d not found\n", LOWORD(pIconId[i]));
              RetPtr[i]=0;
              continue;
-           }
+            }
            xresdir = find_entry_default(xresdir, rootresdir);
-           if (!xresdir)
-           {
-             WARN("icon entry %d not found\n", LOWORD(pIconId[i]));
-             RetPtr[i]=0;
-             continue;
-           }
            idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir;
-           idata = NULL;
 
-           /* map virtual to address in image */
-           for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
-           {
-             if (idataent->OffsetToData < pe_sections[j].VirtualAddress)
-               continue;
-             if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
-               continue;
-             idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
-           }
-           if (!idata)
+        idata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, idataent->OffsetToData, NULL);
+        if (!idata)
            {
              WARN("no matching real address found for icondata!\n");
              RetPtr[i]=0;
@@ -644,7 +625,7 @@ UINT WINAPI PrivateExtractIconExW (
          cxsmicon = GetSystemMetrics(SM_CXSMICON);
          cysmicon = GetSystemMetrics(SM_CYSMICON);
 
-         ret = ICO_ExtractIconExW(lpwstrFile, hIcon, nIndex, 2, cxicon | (cxsmicon<<16),
+          ret = ICO_ExtractIconExW(lpwstrFile, hIcon, nIndex, 2, cxicon | (cxsmicon<<16),
                                   cyicon | (cysmicon<<16), NULL, LR_DEFAULTCOLOR);
          *phIconLarge = hIcon[0];
          *phIconSmall = hIcon[1];