@@ -2623,140 +2623,150 @@ int WINAPI LookupIconIdFromDirectoryEx(
26232623
26242624 TRACE ("%p, %x, %i, %i, %x.\n" , presbits , fIcon , cxDesired , cyDesired , Flags );
26252625
2626- if (!(dir && !dir -> idReserved && (dir -> idType & 3 )))
2626+ /* Wrap the whole implementation in SEH in order to gracefully handle
2627+ * any PE resource corruption case in a simple way. */
2628+ _SEH2_TRY
26272629 {
2628- WARN ("Invalid resource.\n" );
2629- return 0 ;
2630- }
2630+ if (!(dir && !dir -> idReserved && (dir -> idType & 3 )))
2631+ {
2632+ WARN ("Invalid resource.\n" );
2633+ _SEH2_YIELD (return 0 );
2634+ }
26312635
2632- if (Flags & LR_MONOCHROME )
2633- bppDesired = 1 ;
2634- else
2635- {
2636- HDC icScreen ;
2637- icScreen = CreateICW (DISPLAYW , NULL , NULL , NULL );
2638- if (!icScreen )
2639- return FALSE;
2636+ if (Flags & LR_MONOCHROME )
2637+ bppDesired = 1 ;
2638+ else
2639+ {
2640+ HDC icScreen ;
2641+ icScreen = CreateICW (DISPLAYW , NULL , NULL , NULL );
2642+ if (!icScreen )
2643+ _SEH2_YIELD (return 0 );
2644+
2645+ bppDesired = GetDeviceCaps (icScreen , BITSPIXEL );
2646+ DeleteDC (icScreen );
2647+ }
2648+
2649+ if (!cxDesired )
2650+ cxDesired = Flags & LR_DEFAULTSIZE ? GetSystemMetrics (fIcon ? SM_CXICON : SM_CXCURSOR ) : 256 ;
2651+ if (!cyDesired )
2652+ cyDesired = Flags & LR_DEFAULTSIZE ? GetSystemMetrics (fIcon ? SM_CYICON : SM_CYCURSOR ) : 256 ;
2653+
2654+ /* Find the best match for the desired size */
2655+ for (i = 0 ; i < dir -> idCount ; i ++ )
2656+ {
2657+ entry = & dir -> idEntries [i ];
2658+ width = fIcon ? entry -> ResInfo .icon .bWidth : entry -> ResInfo .cursor .wWidth ;
2659+ /* Height is twice as big in cursor resources */
2660+ height = fIcon ? entry -> ResInfo .icon .bHeight : entry -> ResInfo .cursor .wHeight /2 ;
2661+ /* 0 represents 256 */
2662+ if (!width ) width = 256 ;
2663+ if (!height ) height = 256 ;
2664+ /* Calculate the "score" (lower is better) */
2665+ score = 2 * (abs (width - cxDesired ) + abs (height - cyDesired ));
2666+ if ( score > bestScore )
2667+ continue ;
2668+ /* Bigger than requested lowers the score */
2669+ if (width > cxDesired )
2670+ score -= width - cxDesired ;
2671+ if (height > cyDesired )
2672+ score -= height - cyDesired ;
2673+ if (score > bestScore )
2674+ continue ;
2675+ if (score == bestScore )
2676+ {
2677+ if (entry -> wBitCount > BitCount )
2678+ BitCount = entry -> wBitCount ;
2679+ numMatch ++ ;
2680+ continue ;
2681+ }
2682+ iIndex = i ;
2683+ numMatch = 1 ;
2684+ bestScore = score ;
2685+ BitCount = entry -> wBitCount ;
2686+ }
26402687
2641- bppDesired = GetDeviceCaps (icScreen , BITSPIXEL );
2642- DeleteDC (icScreen );
2643- }
2688+ if (numMatch == 1 )
2689+ {
2690+ /* Only one entry fits the asked dimensions */
2691+ _SEH2_YIELD (return dir -> idEntries [iIndex ].wResId );
2692+ }
26442693
2645- if (!cxDesired )
2646- cxDesired = Flags & LR_DEFAULTSIZE ? GetSystemMetrics (fIcon ? SM_CXICON : SM_CXCURSOR ) : 256 ;
2647- if (!cyDesired )
2648- cyDesired = Flags & LR_DEFAULTSIZE ? GetSystemMetrics (fIcon ? SM_CYICON : SM_CYCURSOR ) : 256 ;
2694+ /* Avoid paletted icons on non-paletted device */
2695+ if (bppDesired > 8 && BitCount > 8 )
2696+ notPaletted = TRUE;
26492697
2650- /* Find the best match for the desired size */
2651- for (i = 0 ; i < dir -> idCount ; i ++ )
2652- {
2653- entry = & dir -> idEntries [i ];
2654- width = fIcon ? entry -> ResInfo .icon .bWidth : entry -> ResInfo .cursor .wWidth ;
2655- /* Height is twice as big in cursor resources */
2656- height = fIcon ? entry -> ResInfo .icon .bHeight : entry -> ResInfo .cursor .wHeight /2 ;
2657- /* 0 represents 256 */
2658- if (!width ) width = 256 ;
2659- if (!height ) height = 256 ;
2660- /* Calculate the "score" (lower is better) */
2661- score = 2 * (abs (width - cxDesired ) + abs (height - cyDesired ));
2662- if ( score > bestScore )
2663- continue ;
2664- /* Bigger than requested lowers the score */
2665- if (width > cxDesired )
2666- score -= width - cxDesired ;
2667- if (height > cyDesired )
2668- score -= height - cyDesired ;
2669- if (score > bestScore )
2670- continue ;
2671- if (score == bestScore )
2672- {
2673- if (entry -> wBitCount > BitCount )
2698+ BitCount = 0 ;
2699+ iIndex = -1 ;
2700+ /* Now find the entry with the best depth */
2701+ for (i = 0 ; i < dir -> idCount ; i ++ )
2702+ {
2703+ entry = & dir -> idEntries [i ];
2704+ width = fIcon ? entry -> ResInfo .icon .bWidth : entry -> ResInfo .cursor .wWidth ;
2705+ height = fIcon ? entry -> ResInfo .icon .bHeight : entry -> ResInfo .cursor .wHeight /2 ;
2706+ /* 0 represents 256 */
2707+ if (!width ) width = 256 ;
2708+ if (!height ) height = 256 ;
2709+ /* Check if this is the best match we had */
2710+ score = 2 * (abs (width - cxDesired ) + abs (height - cyDesired ));
2711+ if (width > cxDesired )
2712+ score -= width - cxDesired ;
2713+ if (height > cyDesired )
2714+ score -= height - cyDesired ;
2715+ if (score != bestScore )
2716+ continue ;
2717+ /* Exact match? */
2718+ if (entry -> wBitCount == bppDesired )
2719+ _SEH2_YIELD (return entry -> wResId );
2720+ /* We take the highest possible but smaller than the display depth */
2721+ if ((entry -> wBitCount > BitCount ) && (entry -> wBitCount < bppDesired ))
2722+ {
2723+ /* Avoid paletted icons on non paletted devices */
2724+ if ((entry -> wBitCount <= 8 ) && notPaletted )
2725+ continue ;
2726+ iIndex = i ;
26742727 BitCount = entry -> wBitCount ;
2675- numMatch ++ ;
2676- continue ;
2728+ }
26772729 }
2678- iIndex = i ;
2679- numMatch = 1 ;
2680- bestScore = score ;
2681- BitCount = entry -> wBitCount ;
2682- }
26832730
2684- if (numMatch == 1 )
2685- {
2686- /* Only one entry fits the asked dimensions */
2687- return dir -> idEntries [iIndex ].wResId ;
2688- }
2689-
2690- /* Avoid paletted icons on non-paletted device */
2691- if (bppDesired > 8 && BitCount > 8 )
2692- notPaletted = TRUE;
2693-
2694- BitCount = 0 ;
2695- iIndex = -1 ;
2696- /* Now find the entry with the best depth */
2697- for (i = 0 ; i < dir -> idCount ; i ++ )
2698- {
2699- entry = & dir -> idEntries [i ];
2700- width = fIcon ? entry -> ResInfo .icon .bWidth : entry -> ResInfo .cursor .wWidth ;
2701- height = fIcon ? entry -> ResInfo .icon .bHeight : entry -> ResInfo .cursor .wHeight /2 ;
2702- /* 0 represents 256 */
2703- if (!width ) width = 256 ;
2704- if (!height ) height = 256 ;
2705- /* Check if this is the best match we had */
2706- score = 2 * (abs (width - cxDesired ) + abs (height - cyDesired ));
2707- if (width > cxDesired )
2708- score -= width - cxDesired ;
2709- if (height > cyDesired )
2710- score -= height - cyDesired ;
2711- if (score != bestScore )
2712- continue ;
2713- /* Exact match? */
2714- if (entry -> wBitCount == bppDesired )
2715- return entry -> wResId ;
2716- /* We take the highest possible but smaller than the display depth */
2717- if ((entry -> wBitCount > BitCount ) && (entry -> wBitCount < bppDesired ))
2718- {
2719- /* Avoid paletted icons on non paletted devices */
2720- if ((entry -> wBitCount <= 8 ) && notPaletted )
2731+ if (iIndex >= 0 )
2732+ _SEH2_YIELD (return dir -> idEntries [iIndex ].wResId );
2733+
2734+ /* No inferior or equal depth available. Get the smallest bigger one */
2735+ BitCount = 0xFFFF ;
2736+ iIndex = -1 ;
2737+ for (i = 0 ; i < dir -> idCount ; i ++ )
2738+ {
2739+ entry = & dir -> idEntries [i ];
2740+ width = fIcon ? entry -> ResInfo .icon .bWidth : entry -> ResInfo .cursor .wWidth ;
2741+ height = fIcon ? entry -> ResInfo .icon .bHeight : entry -> ResInfo .cursor .wHeight /2 ;
2742+ /* 0 represents 256 */
2743+ if (!width ) width = 256 ;
2744+ if (!height ) height = 256 ;
2745+ /* Check if this is the best match we had */
2746+ score = 2 * (abs (width - cxDesired ) + abs (height - cyDesired ));
2747+ if (width > cxDesired )
2748+ score -= width - cxDesired ;
2749+ if (height > cyDesired )
2750+ score -= height - cyDesired ;
2751+ if (score != bestScore )
27212752 continue ;
2722- iIndex = i ;
2723- BitCount = entry -> wBitCount ;
2753+ /* Check the bit depth */
2754+ if (entry -> wBitCount < BitCount )
2755+ {
2756+ if ((entry -> wBitCount <= 8 ) && notPaletted )
2757+ continue ;
2758+ iIndex = i ;
2759+ BitCount = entry -> wBitCount ;
2760+ }
27242761 }
2762+ if (iIndex >= 0 )
2763+ _SEH2_YIELD (return dir -> idEntries [iIndex ].wResId );
27252764 }
2726-
2727- if (iIndex >= 0 )
2728- return dir -> idEntries [iIndex ].wResId ;
2729-
2730- /* No inferior or equal depth available. Get the smallest bigger one */
2731- BitCount = 0xFFFF ;
2732- iIndex = -1 ;
2733- for (i = 0 ; i < dir -> idCount ; i ++ )
2765+ _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER )
27342766 {
2735- entry = & dir -> idEntries [i ];
2736- width = fIcon ? entry -> ResInfo .icon .bWidth : entry -> ResInfo .cursor .wWidth ;
2737- height = fIcon ? entry -> ResInfo .icon .bHeight : entry -> ResInfo .cursor .wHeight /2 ;
2738- /* 0 represents 256 */
2739- if (!width ) width = 256 ;
2740- if (!height ) height = 256 ;
2741- /* Check if this is the best match we had */
2742- score = 2 * (abs (width - cxDesired ) + abs (height - cyDesired ));
2743- if (width > cxDesired )
2744- score -= width - cxDesired ;
2745- if (height > cyDesired )
2746- score -= height - cyDesired ;
2747- if (score != bestScore )
2748- continue ;
2749- /* Check the bit depth */
2750- if (entry -> wBitCount < BitCount )
2751- {
2752- if ((entry -> wBitCount <= 8 ) && notPaletted )
2753- continue ;
2754- iIndex = i ;
2755- BitCount = entry -> wBitCount ;
2756- }
2767+ ERR ("Invalid resource (0x%p)\n" , presbits );
27572768 }
2758- if (iIndex >= 0 )
2759- return dir -> idEntries [iIndex ].wResId ;
2769+ _SEH2_END ;
27602770
27612771 return 0 ;
27622772}
0 commit comments