* Sync up to trunk head (r65298).

svn path=/branches/shell-experiments/; revision=65299
This commit is contained in:
Amine Khaldi 2014-11-06 19:24:18 +00:00
parent 2060ee5d9c
commit e8103dd4d3
12 changed files with 229 additions and 158 deletions

View file

@ -565,11 +565,14 @@ VfatCreateFile(
LONG idx, FileNameLen; LONG idx, FileNameLen;
ParentFcb = (FileObject->RelatedFileObject != NULL) ? FileObject->RelatedFileObject->FsContext : NULL; ParentFcb = (FileObject->RelatedFileObject != NULL) ? FileObject->RelatedFileObject->FsContext : NULL;
Status = vfatGetFCBForFile(DeviceExt, &ParentFcb, &TargetFcb, &PathNameU); if (ParentFcb)
if (Status == STATUS_SUCCESS)
{ {
vfatGrabFCB(DeviceExt, ParentFcb); vfatGrabFCB(DeviceExt, ParentFcb);
}
Status = vfatGetFCBForFile(DeviceExt, &ParentFcb, &TargetFcb, &PathNameU);
if (NT_SUCCESS(Status))
{
vfatReleaseFCB(DeviceExt, TargetFcb); vfatReleaseFCB(DeviceExt, TargetFcb);
Irp->IoStatus.Information = FILE_EXISTS; Irp->IoStatus.Information = FILE_EXISTS;
} }
@ -580,7 +583,7 @@ VfatCreateFile(
idx = FileObject->FileName.Length / sizeof(WCHAR) - 1; idx = FileObject->FileName.Length / sizeof(WCHAR) - 1;
/* Skip tailing \ - if any */ /* Skip trailing \ - if any */
if (PathNameU.Buffer[idx] == L'\\') if (PathNameU.Buffer[idx] == L'\\')
{ {
--idx; --idx;
@ -623,6 +626,7 @@ VfatCreateFile(
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
pFcb = FileObject->FsContext; pFcb = FileObject->FsContext;
ASSERT(pFcb == ParentFcb);
if (pFcb->OpenHandleCount == 0) if (pFcb->OpenHandleCount == 0)
{ {
@ -640,7 +644,6 @@ VfatCreateFile(
FALSE); FALSE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
vfatReleaseFCB(DeviceExt, ParentFcb);
VfatCloseFile(DeviceExt, FileObject); VfatCloseFile(DeviceExt, FileObject);
return Status; return Status;
} }

View file

@ -201,12 +201,6 @@ FATGetNextDirEntry(
CcUnpinData(*pContext); 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 || if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
{ {

View file

@ -167,11 +167,6 @@ vfatFindDirSpace(
{ {
CcUnpinData(Context); 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, if (!CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster,
TRUE, &Context, (PVOID*)&pFatEntry)) TRUE, &Context, (PVOID*)&pFatEntry))
{ {

View file

@ -371,6 +371,13 @@ vfatUpdateFCB(
DPRINT("vfatUpdateFCB(%p, %p, %wZ, %wZ, %p)\n", pVCB, Fcb, LongName, ShortName, ParentFcb); 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 */ /* Delete old name */
if (Fcb->PathNameBuffer) if (Fcb->PathNameBuffer)
{ {
@ -380,13 +387,6 @@ vfatUpdateFCB(
/* Delete from table */ /* Delete from table */
vfatDelFCBFromTable(pVCB, Fcb); vfatDelFCBFromTable(pVCB, Fcb);
/* Get full path name */
Status = vfatMakeFullName(ParentFcb, LongName, ShortName, &Fcb->PathNameU);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Split it properly */ /* Split it properly */
Fcb->PathNameBuffer = Fcb->PathNameU.Buffer; Fcb->PathNameBuffer = Fcb->PathNameU.Buffer;
Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer; Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
@ -414,8 +414,8 @@ vfatUpdateFCB(
/* Add to the table */ /* Add to the table */
vfatAddFCBToTable(pVCB, Fcb); vfatAddFCBToTable(pVCB, Fcb);
/* If we moved accross directories, dereferenced our old parent /* If we moved across directories, dereference our old parent
* We also derefence in case we're just renaming since AddFCBToTable references it * We also dereference in case we're just renaming since AddFCBToTable references it
*/ */
vfatReleaseFCB(pVCB, OldParent); vfatReleaseFCB(pVCB, OldParent);
@ -887,7 +887,7 @@ vfatGetFCBForFile(
if (parentFCB) if (parentFCB)
{ {
vfatReleaseFCB(pVCB, parentFCB); vfatReleaseFCB(pVCB, parentFCB);
parentFCB = 0; parentFCB = NULL;
} }
// fail if element in FCB is not a directory // fail if element in FCB is not a directory
if (!vfatFCBIsDirectory(FCB)) if (!vfatFCBIsDirectory(FCB))
@ -910,6 +910,8 @@ vfatGetFCBForFile(
if (FileNameU.Length + parentFCB->LongNameU.Length - Length > FileNameU.MaximumLength) if (FileNameU.Length + parentFCB->LongNameU.Length - Length > FileNameU.MaximumLength)
{ {
vfatReleaseFCB(pVCB, parentFCB); vfatReleaseFCB(pVCB, parentFCB);
*pParentFCB = NULL;
*pFCB = NULL;
return STATUS_OBJECT_NAME_INVALID; return STATUS_OBJECT_NAME_INVALID;
} }
RtlMoveMemory(prev + parentFCB->LongNameU.Length / sizeof(WCHAR), curr, RtlMoveMemory(prev + parentFCB->LongNameU.Length / sizeof(WCHAR), curr,

View file

@ -106,6 +106,13 @@ Fast486ReadMemory(PFAST486_STATE State,
/* We mustn't prefetch across a page boundary */ /* We mustn't prefetch across a page boundary */
State->PrefetchAddress = PAGE_ALIGN(State->PrefetchAddress) State->PrefetchAddress = PAGE_ALIGN(State->PrefetchAddress)
| (FAST486_PAGE_SIZE - FAST486_CACHE_SIZE); | (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 */ /* Prefetch */
@ -546,7 +553,12 @@ Fast486TaskSwitch(PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Se
/* Calculate the limit of the new TSS */ /* Calculate the limit of the new TSS */
NewTssLimit = NewTssDescriptor.Limit | (NewTssDescriptor.LimitHigh << 16); NewTssLimit = NewTssDescriptor.Limit | (NewTssDescriptor.LimitHigh << 16);
if (NewTssDescriptor.Granularity) NewTssLimit <<= 12;
if (NewTssDescriptor.Granularity)
{
NewTssLimit <<= 12;
NewTssLimit |= 0x00000FFF;
}
if (NewTssLimit < sizeof(FAST486_TSS)) 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.Selector = NewTss.Ldtr;
State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24); State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); 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 else
{ {

View file

@ -594,16 +594,12 @@ Fast486LoadSegmentInternal(PFAST486_STATE State,
{ {
/* Regular code segment */ /* Regular code segment */
if ((GET_SEGMENT_RPL(Selector) > Fast486GetCurrentPrivLevel(State)) if ((GET_SEGMENT_RPL(Selector) < Fast486GetCurrentPrivLevel(State)))
|| (Fast486GetCurrentPrivLevel(State) != GdtEntry.Dpl))
{ {
Fast486ExceptionWithErrorCode(State, Exception, Selector); Fast486ExceptionWithErrorCode(State, Exception, Selector);
return FALSE; return FALSE;
} }
} }
/* Update CPL */
State->Cpl = GET_SEGMENT_RPL(Selector);
} }
else else
{ {
@ -653,7 +649,11 @@ Fast486LoadSegmentInternal(PFAST486_STATE State,
CachedDescriptor->Size = GdtEntry.Size; CachedDescriptor->Size = GdtEntry.Size;
/* Check for page granularity */ /* Check for page granularity */
if (GdtEntry.Granularity) CachedDescriptor->Limit <<= 12; if (GdtEntry.Granularity)
{
CachedDescriptor->Limit <<= 12;
CachedDescriptor->Limit |= 0x00000FFF;
}
} }
else else
{ {
@ -730,6 +730,13 @@ Fast486ProcessGate(PFAST486_STATE State, USHORT Selector, ULONG Offset, BOOLEAN
default: default:
{ {
/* Security check for jumps and calls only */
if (State->Cpl != Descriptor.Dpl)
{
Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
return FALSE;
}
return TRUE; return TRUE;
} }
} }

View file

@ -475,7 +475,12 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLsl)
/* Calculate the limit */ /* Calculate the limit */
Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
if (GdtEntry.Granularity) Limit <<= 12;
if (GdtEntry.Granularity)
{
Limit <<= 12;
Limit |= 0x00000FFF;
}
/* Set ZF */ /* Set ZF */
State->Flags.Zf = TRUE; State->Flags.Zf = TRUE;

View file

@ -4474,6 +4474,63 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeRetFar)
return; 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 */ /* Load new (E)IP, and if necessary, pop the parameters */
if (Size) if (Size)
{ {
@ -4582,7 +4639,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
/* Check for protected mode */ /* Check for protected mode */
if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
{ {
INT Cpl = Fast486GetCurrentPrivLevel(State); INT OldCpl = Fast486GetCurrentPrivLevel(State);
if (State->Flags.Vm) if (State->Flags.Vm)
{ {
@ -4660,7 +4717,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
if (Size) State->InstPtr.Long = InstPtr; if (Size) State->InstPtr.Long = InstPtr;
else State->InstPtr.LowWord = LOWORD(InstPtr); else State->InstPtr.LowWord = LOWORD(InstPtr);
if (GET_SEGMENT_RPL(CodeSel) > Cpl) if (GET_SEGMENT_RPL(CodeSel) > OldCpl)
{ {
/* Pop ESP */ /* Pop ESP */
if (!Fast486StackPop(State, &StackPtr)) if (!Fast486StackPop(State, &StackPtr))
@ -4675,7 +4732,22 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
/* Exception */ /* Exception */
return; 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 */ /* Load new SS */
if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel)) if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel))
{ {
@ -4686,21 +4758,6 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
/* Set ESP */ /* Set ESP */
if (Size) State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr; if (Size) State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr;
else State->GeneralRegs[FAST486_REG_ESP].LowWord = LOWORD(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 */ /* Check segment security */
for (i = 0; i < FAST486_NUM_SEG_REGS; i++) for (i = 0; i < FAST486_NUM_SEG_REGS; i++)
@ -4708,7 +4765,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
/* Don't check CS or SS */ /* Don't check CS or SS */
if ((i == FAST486_REG_CS) || (i == FAST486_REG_SS)) continue; 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].Executable
|| !State->SegmentRegs[i].DirConf)) || !State->SegmentRegs[i].DirConf))
{ {

View file

@ -1804,7 +1804,12 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
State->Ldtr.Selector = Selector; State->Ldtr.Selector = Selector;
State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24); State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); 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; break;
} }
@ -1886,7 +1891,12 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
State->TaskReg.Selector = Selector; State->TaskReg.Selector = Selector;
State->TaskReg.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24); State->TaskReg.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
State->TaskReg.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); 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; break;
} }

View file

@ -1580,8 +1580,8 @@ IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
if (OpenPacket.ParseCheck != TRUE) if (OpenPacket.ParseCheck != TRUE)
{ {
/* Parse failed */ /* Parse failed */
DPRINT1("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n", DPRINT("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n",
ObjectAttributes->ObjectName, Status); ObjectAttributes->ObjectName, Status);
return Status; return Status;
} }
else else

View file

@ -1132,7 +1132,7 @@ NtGdiExtFloodFill(
goto cleanup; goto cleanup;
} }
else 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); DC_vPrepareDCsForBlit(dc, &DestRect, NULL, NULL);

View 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 ) if (*((DWORD*)(peimage + mz_header->e_lfanew)) == IMAGE_NT_SIGNATURE )
return IMAGE_NT_SIGNATURE; return IMAGE_NT_SIGNATURE;
#if 0 #ifdef WINE
if (*((WORD*)(peimage + mz_header->e_lfanew)) == IMAGE_OS2_SIGNATURE ) if (*((WORD*)(peimage + mz_header->e_lfanew)) == IMAGE_OS2_SIGNATURE )
{ {
IMAGE_OS2_HEADER * ne_header; IMAGE_OS2_HEADER * ne_header;
@ -132,7 +132,7 @@ static DWORD USER32_GetResourceTable(LPBYTE peimage,DWORD pesize,LPBYTE *retptr)
#endif #endif
return 0; /* failed */ return 0; /* failed */
} }
#if 0 #ifdef WINE
/************************************************************************* /*************************************************************************
* USER32_LoadResource * USER32_LoadResource
*/ */
@ -160,9 +160,6 @@ static BYTE * ICO_LoadIcon( LPBYTE peimage, LPicoICONDIRENTRY lpiIDE, ULONG *uSi
* *
* Reads .ico file and build phony ICONDIR struct * 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 ) static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG *uSize )
{ {
CURSORICONDIR * lpcid; /* icon resource in resource-dir format */ CURSORICONDIR * lpcid; /* icon resource in resource-dir format */
@ -177,7 +174,7 @@ static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG
return 0; return 0;
/* allocate the phony ICONDIR structure */ /* 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) )) if( (lpID = HeapAlloc(GetProcessHeap(),0, *uSize) ))
{ {
/* copy the header */ /* copy the header */
@ -188,7 +185,7 @@ static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG
/* copy the entries */ /* copy the entries */
for( i=0; i < lpcid->idCount; i++ ) 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; lpID->idEntries[i].wResId = i;
} }
@ -224,7 +221,7 @@ static UINT ICO_ExtractIconExW(
LPBYTE pData; LPBYTE pData;
DWORD sig; DWORD sig;
HANDLE hFile; HANDLE hFile;
UINT16 iconDirCount = 0; //,iconCount = 0; UINT16 iconDirCount = 0, iconCount = 0;
LPBYTE peimage; LPBYTE peimage;
HANDLE fmapping; HANDLE fmapping;
DWORD fsizeh,fsizel; DWORD fsizeh,fsizel;
@ -274,8 +271,8 @@ static UINT ICO_ExtractIconExW(
sig = USER32_GetResourceTable(peimage, fsizel, &pData); sig = USER32_GetResourceTable(peimage, fsizel, &pData);
#ifdef WINE
/* ico file or NE exe/dll*/ /* ico file or NE exe/dll*/
#if 0
if (sig==IMAGE_OS2_SIGNATURE || sig==1) /* .ICO file */ if (sig==IMAGE_OS2_SIGNATURE || sig==1) /* .ICO file */
{ {
BYTE *pCIDir = 0; BYTE *pCIDir = 0;
@ -283,8 +280,9 @@ static UINT ICO_ExtractIconExW(
NE_NAMEINFO *pIconStorage = NULL; NE_NAMEINFO *pIconStorage = NULL;
NE_NAMEINFO *pIconDir = NULL; NE_NAMEINFO *pIconDir = NULL;
LPicoICONDIR lpiID = 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) if (pData == (BYTE*)-1)
{ {
@ -292,7 +290,7 @@ static UINT ICO_ExtractIconExW(
if (pCIDir) if (pCIDir)
{ {
iconDirCount = 1; iconCount = lpiID->idCount; 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)) else while (pTInfo->type_id && !(pIconStorage && pIconDir))
@ -317,7 +315,7 @@ static UINT ICO_ExtractIconExW(
if (nIcons == 0) if (nIcons == 0)
{ {
ret = iconDirCount; ret = iconDirCount;
if (lpiID && pCIDir) /* *.ico file, deallocate heap pointer*/ if (lpiID) /* *.ico file, deallocate heap pointer*/
HeapFree(GetProcessHeap(), 0, pCIDir); HeapFree(GetProcessHeap(), 0, pCIDir);
} }
else if (nIconIndex < iconDirCount) else if (nIconIndex < iconDirCount)
@ -331,9 +329,10 @@ static UINT ICO_ExtractIconExW(
/* .ICO files have only one icon directory */ /* .ICO files have only one icon directory */
if (lpiID == NULL) /* not *.ico */ if (lpiID == NULL) /* not *.ico */
pCIDir = USER32_LoadResource(peimage, pIconDir + i + nIconIndex, *(WORD*)pData, &uSize); 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); HeapFree(GetProcessHeap(), 0, pCIDir);
for (icon = 0; icon < nIcons; icon++) for (icon = 0; icon < nIcons; icon++)
@ -347,8 +346,13 @@ static UINT ICO_ExtractIconExW(
pCIDir = USER32_LoadResource(peimage, pIconStorage + i, *(WORD*)pData, &uSize); pCIDir = USER32_LoadResource(peimage, pIconStorage + i, *(WORD*)pData, &uSize);
if (pCIDir) 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 else
RetPtr[icon] = 0; 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 */ /* end ico file */
/* exe/dll */ /* exe/dll */
else if( sig == IMAGE_NT_SIGNATURE ) else if( sig == IMAGE_NT_SIGNATURE )
#endif
if( sig == IMAGE_NT_SIGNATURE )
{ {
LPBYTE idata,igdata; BYTE *idata, *igdata;
PIMAGE_DOS_HEADER dheader; const IMAGE_RESOURCE_DIRECTORY *rootresdir, *iconresdir, *icongroupresdir;
PIMAGE_NT_HEADERS pe_header; const IMAGE_RESOURCE_DATA_ENTRY *idataent, *igdataent;
PIMAGE_SECTION_HEADER pe_sections; const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
const IMAGE_RESOURCE_DIRECTORY *rootresdir,*iconresdir,*icongroupresdir; ULONG size;
const IMAGE_RESOURCE_DATA_ENTRY *idataent,*igdataent; UINT i;
const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
UINT i, j;
dheader = (PIMAGE_DOS_HEADER)peimage; rootresdir = RtlImageDirectoryEntryToData((HMODULE)peimage, FALSE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size);
pe_header = (PIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew); /* it is a pe header, USER32_GetResourceTable checked that */ if (!rootresdir)
pe_sections = (PIMAGE_SECTION_HEADER)(((char*)pe_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) {
+ pe_header->FileHeader.SizeOfOptionalHeader); WARN("haven't found section for resource directory.\n");
rootresdir = NULL; goto end;
}
/* 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 */
}
/* search for the group icon directory */ /* search for the group icon directory */
if (!(icongroupresdir = find_entry_by_id(rootresdir, LOWORD(RT_GROUP_ICON), rootresdir))) 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; const IMAGE_RESOURCE_DIRECTORY *resdir;
/* go down this resource entry, name */ /* 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) */ /* default language (0) */
resdir = find_entry_default(resdir,rootresdir); resdir = find_entry_default(resdir,rootresdir);
igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir; igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir;
/* lookup address in mapped image for virtual address */ /* lookup address in mapped image for virtual address */
igdata = NULL; igdata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, igdataent->OffsetToData, NULL);
if (!igdata)
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)
{ {
FIXME("no matching real address for icongroup!\n"); FIXME("no matching real address for icongroup!\n");
goto end; /* failure */ goto end; /* failure */
} }
pIconId[i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx1, cy1, flags); 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))) if (!(iconresdir=find_entry_by_id(rootresdir,LOWORD(RT_ICON),rootresdir)))
@ -508,32 +504,17 @@ static UINT ICO_ExtractIconExW(
{ {
const IMAGE_RESOURCE_DIRECTORY *xresdir; const IMAGE_RESOURCE_DIRECTORY *xresdir;
xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir); xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir);
if (!xresdir) if( !xresdir )
{ {
WARN("icon entry %d not found\n", LOWORD(pIconId[i])); WARN("icon entry %d not found\n", LOWORD(pIconId[i]));
RetPtr[i]=0; RetPtr[i]=0;
continue; continue;
} }
xresdir = find_entry_default(xresdir, rootresdir); 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; idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir;
idata = NULL;
/* map virtual to address in image */ idata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, idataent->OffsetToData, NULL);
for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) if (!idata)
{
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)
{ {
WARN("no matching real address found for icondata!\n"); WARN("no matching real address found for icondata!\n");
RetPtr[i]=0; RetPtr[i]=0;
@ -644,7 +625,7 @@ UINT WINAPI PrivateExtractIconExW (
cxsmicon = GetSystemMetrics(SM_CXSMICON); cxsmicon = GetSystemMetrics(SM_CXSMICON);
cysmicon = GetSystemMetrics(SM_CYSMICON); 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); cyicon | (cysmicon<<16), NULL, LR_DEFAULTCOLOR);
*phIconLarge = hIcon[0]; *phIconLarge = hIcon[0];
*phIconSmall = hIcon[1]; *phIconSmall = hIcon[1];