[WIN32K/USER32]

- Simplify an overcomplicated way to get buffer size from win32k
 - Do not spaghettize between string length and buffer size.
 - Properly use GetModuleFileName.

svn path=/trunk/; revision=64938
This commit is contained in:
Jérôme Gardou 2014-10-23 19:41:42 +00:00
parent a8e3dcc9e1
commit 25c228cd3f
2 changed files with 64 additions and 71 deletions

View file

@ -187,7 +187,8 @@ IntDestroyCurIconObject(
/* We just mark the handle as being destroyed. /* We just mark the handle as being destroyed.
* Deleting all the stuff will be deferred to the actual struct free. */ * Deleting all the stuff will be deferred to the actual struct free. */
return UserDeleteObject(CurIcon->head.h, TYPE_CURSOR); UserDeleteObject(CurIcon->head.h, TYPE_CURSOR);
return TRUE;
} }
void void
@ -357,16 +358,18 @@ NtUserGetIconInfo(
/* Get the module name from the atom table */ /* Get the module name from the atom table */
_SEH2_TRY _SEH2_TRY
{ {
if (BufLen > (lpModule->MaximumLength * sizeof(WCHAR))) BufLen += sizeof(WCHAR);
if (BufLen > (lpModule->MaximumLength))
{ {
lpModule->Length = 0; lpModule->Length = 0;
lpModule->MaximumLength = BufLen;
} }
else else
{ {
ProbeForWrite(lpModule->Buffer, lpModule->MaximumLength, 1); ProbeForWrite(lpModule->Buffer, lpModule->MaximumLength, 1);
BufLen = lpModule->MaximumLength * sizeof(WCHAR); BufLen = lpModule->MaximumLength;
RtlQueryAtomInAtomTable(gAtomTable, CurIcon->atomModName, NULL, NULL, lpModule->Buffer, &BufLen); RtlQueryAtomInAtomTable(gAtomTable, CurIcon->atomModName, NULL, NULL, lpModule->Buffer, &BufLen);
lpModule->Length = BufLen/sizeof(WCHAR); lpModule->Length = BufLen;
} }
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@ -395,15 +398,18 @@ NtUserGetIconInfo(
{ {
lpResName->Buffer = CurIcon->strName.Buffer; lpResName->Buffer = CurIcon->strName.Buffer;
lpResName->Length = 0; lpResName->Length = 0;
lpResName->MaximumLength = 0;
} }
else if (lpResName->MaximumLength < CurIcon->strName.Length) else if (lpResName->MaximumLength < CurIcon->strName.MaximumLength)
{ {
lpResName->Length = 0; lpResName->Length = 0;
lpResName->MaximumLength = CurIcon->strName.MaximumLength;
} }
else else
{ {
ProbeForWrite(lpResName->Buffer, lpResName->MaximumLength * sizeof(WCHAR), 1); ProbeForWrite(lpResName->Buffer, lpResName->MaximumLength, 1);
RtlCopyMemory(lpResName->Buffer, CurIcon->strName.Buffer, lpResName->Length); RtlCopyMemory(lpResName->Buffer, CurIcon->strName.Buffer, CurIcon->strName.Length);
lpResName->Length = CurIcon->strName.Length;
} }
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)

View file

@ -1342,27 +1342,37 @@ CURSORICON_LoadImageW(
} }
else else
RtlInitUnicodeString(&ustrRsrc, lpszName); RtlInitUnicodeString(&ustrRsrc, lpszName);
/* Prepare the module name string */ /* Get the module name string */
ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR)); while (TRUE)
/* Get it */
do
{ {
DWORD ret = GetModuleFileNameW(hinst, ustrModule.Buffer, size); DWORD ret;
ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
if (!ustrModule.Buffer)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
ret = GetModuleFileNameW(hinst, ustrModule.Buffer, size);
if(ret == 0) if(ret == 0)
{ {
HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
return NULL; return NULL;
} }
if(ret < size)
/* This API is completely broken... */
if (ret == size)
{ {
ustrModule.Length = ret*sizeof(WCHAR); HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
ustrModule.MaximumLength = size*sizeof(WCHAR); size *= 2;
break; continue;
} }
size *= 2;
ustrModule.Buffer = HeapReAlloc(GetProcessHeap(), 0, ustrModule.Buffer, size*sizeof(WCHAR)); ustrModule.Buffer[ret] = UNICODE_NULL;
} while(TRUE); ustrModule.Length = ret * sizeof(WCHAR);
ustrModule.MaximumLength = size * sizeof(WCHAR);
break;
}
/* Ask win32k */ /* Ask win32k */
param.bIcon = bIcon; param.bIcon = bIcon;
@ -1691,75 +1701,51 @@ CURSORICON_CopyImage(
/* Get the icon module/resource names */ /* Get the icon module/resource names */
UNICODE_STRING ustrModule; UNICODE_STRING ustrModule;
UNICODE_STRING ustrRsrc; UNICODE_STRING ustrRsrc;
PVOID pvBuf;
HMODULE hModule; HMODULE hModule;
ustrModule.MaximumLength = MAX_PATH * sizeof(WCHAR); ustrModule.MaximumLength = 0;
ustrRsrc.MaximumLength = 256; ustrRsrc.MaximumLength = 0;
/* Get the buffer size */
if (!NtUserGetIconInfo(hicon, NULL, &ustrModule, &ustrRsrc, NULL, FALSE))
{
return NULL;
}
ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, ustrModule.MaximumLength); ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, ustrModule.MaximumLength);
if (!ustrModule.Buffer) if (!ustrModule.Buffer)
{ {
SetLastError(ERROR_NOT_ENOUGH_MEMORY); SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL; return NULL;
} }
/* Keep track of the buffer for the resource, NtUserGetIconInfo might overwrite it */
pvBuf = HeapAlloc(GetProcessHeap(), 0, ustrRsrc.MaximumLength);
if (!pvBuf)
{
HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
ustrRsrc.Buffer = pvBuf;
do if (ustrRsrc.MaximumLength)
{ {
if (!NtUserGetIconInfo(hicon, NULL, &ustrModule, &ustrRsrc, NULL, FALSE)) ustrRsrc.Buffer = HeapAlloc(GetProcessHeap(), 0, ustrRsrc.MaximumLength);
if (!ustrRsrc.Buffer)
{ {
HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
HeapFree(GetProcessHeap(), 0, pvBuf); SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL; return NULL;
} }
}
if (ustrModule.Length && (ustrRsrc.Length || IS_INTRESOURCE(ustrRsrc.Buffer)))
{ if (!NtUserGetIconInfo(hicon, NULL, &ustrModule, &ustrRsrc, NULL, FALSE))
/* Buffers were big enough */ {
break; HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
} if (!IS_INTRESOURCE(ustrRsrc.Buffer))
HeapFree(GetProcessHeap(), 0, ustrRsrc.Buffer);
/* Find which buffer were too small */ return NULL;
if (!ustrModule.Length) }
{
PWSTR newBuffer;
ustrModule.MaximumLength *= 2;
newBuffer = HeapReAlloc(GetProcessHeap(), 0, ustrModule.Buffer, ustrModule.MaximumLength);
if(!ustrModule.Buffer)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto leave;
}
ustrModule.Buffer = newBuffer;
}
if (!ustrRsrc.Length)
{
ustrRsrc.MaximumLength *= 2;
pvBuf = HeapReAlloc(GetProcessHeap(), 0, ustrRsrc.Buffer, ustrRsrc.MaximumLength);
if (!pvBuf)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto leave;
}
ustrRsrc.Buffer = pvBuf;
}
} while(TRUE);
/* NULL-terminate our strings */ /* NULL-terminate our strings */
ustrModule.Buffer[ustrModule.Length/sizeof(WCHAR)] = 0; ustrModule.Buffer[ustrModule.Length/sizeof(WCHAR)] = UNICODE_NULL;
if (!IS_INTRESOURCE(ustrRsrc.Buffer)) if (!IS_INTRESOURCE(ustrRsrc.Buffer))
ustrRsrc.Buffer[ustrRsrc.Length/sizeof(WCHAR)] = 0; ustrRsrc.Buffer[ustrRsrc.Length/sizeof(WCHAR)] = UNICODE_NULL;
TRACE("Got module %S, resource %p (%S).\n", ustrModule.Buffer,
ustrRsrc.Buffer, IS_INTRESOURCE(ustrRsrc.Buffer) ? L"" : ustrRsrc.Buffer);
/* Get the module handle */ /* Get the module handle */
if (!GetModuleHandleExW(0, ustrModule.Buffer, &hModule)) if (!GetModuleHandleExW(0, ustrModule.Buffer, &hModule))
{ {
@ -1783,7 +1769,8 @@ CURSORICON_CopyImage(
/* If we're here, that means that the passed icon is shared. Don't destroy it, even if LR_COPYDELETEORG is specified */ /* If we're here, that means that the passed icon is shared. Don't destroy it, even if LR_COPYDELETEORG is specified */
leave: leave:
HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
HeapFree(GetProcessHeap(), 0, pvBuf); if (!IS_INTRESOURCE(ustrRsrc.Buffer))
HeapFree(GetProcessHeap(), 0, ustrRsrc.Buffer);
TRACE("Returning 0x%08x.\n", ret); TRACE("Returning 0x%08x.\n", ret);