News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Loading Icons From Shell32.dll

Started by xandaz, August 23, 2009, 02:39:42 PM

Previous topic - Next topic

maruf10

Quote from: Tedd on August 24, 2009, 09:25:53 AM

For file-type icons you can use SHGetFileInfo, which gives you an index into the system image list - you then draw the icon directly from there with ImageList_Draw.


Would you please provide a sample && simple code which takes file path as parameter and return that files index from system image list ??

i am using SHGetFileInfo .but iIcon is not working at all ....
Thanks in advance ...

donkey

Hi,

It depends what you're doing with the icon, normally you would use it in a listview. First off for SHGetFileInfo you have to realize that it is an index into the icon cache, not any particular DLL. In order to obtain a handle to the icon cache you need to use:

invoke Shell_GetImageLists,OFFSET hSysImlLarge,OFFSET hSysImlSmall

for some Windows versions you will have to call it by ordinal, it is ordinal 71 in Shell32.dll. Normally you would assign the imagelist returned to the listviiew, be sure to set the style to LVS_SHAREIMAGELISTS otherwise you'll trash the icon cache when it is destroyed and will have to restart to get it back.

Once you have the icon cache and have set it as your listviews imagelist, you use SHGetFileInfo to get the index in the list:

invoke SHGetFileInfo,OFFSET szPath,NULL,OFFSET sfi,SIZEOF SHFILEINFO,SHGFI_SYSICONINDEX

The sfi.iIcon member will point to the icon in the shell image list, use this index when setting the LVITEM.iImage member.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

maruf10

I just want to print file path and its corresponding  icon index  :'(

here is the code portion :



.DATA

hSysImlLarge HIMAGELIST ?
hSysImlSmall HIMAGELIST ?

.CODE

invoke Shell_GetImageLists,OFFSET hSysImlLarge,OFFSET hSysImlSmall
invoke SHGetFileInfo,OFFSET FilePath,NULL,OFFSET shfi,SIZEOF shfi,SHGFI_SYSICONINDEX

invoke StdOut , OFFSET FilePath
                   
mov ebx , shfi.iIcon
invoke dwtoa , ebx ,addr BUFFER
invoke StdOut , addr BUFFER



would you please correct this code ..??
I think i am not using Shell_GetImageLists and SHGetFileInfo correctly  :(

Greenhorn__

Hi,

for details on this topic I recommend to read this article here ...
http://www.catch22.net/tuts/sysimg

But it's also possible to do it as dedndave first pointed to with LoadImage or ExtractIconEx.
It's your decision how to implement it ... ;)


Greenhorn
You can fool some of the people all of the time, and all of the people some of the time, but you can not fool all of the people all of the time.
(Abraham Lincoln)

maruf10

#19
Thanks for that link ...
But i'm still in dark ...

all these are telling about handle ...

Quote
SHGetFileInfo returns a handle to the system imagelist, and stores the index of the requested icon type in the SHFILEINFO structure.

how can i use that handle to get system icon index for a specific file ...??
according to Edgar i have just got the cached icon index for a file using this portion :


invoke SHGetFileInfo,OFFSET FilePath,NULL,OFFSET shfi,SIZEOF shfi,SHGFI_ICON OR SHGFI_SYSICONINDEX

mov ebx , shfi.iIcon
invoke dwtoa , ebx ,addr BUFFER
invoke StdOut , addr BUFFER



shfi.hIcon will store the handle ?? isn't it ??
any working module ??

Thanks in advance  :red

qWord

Quote from: maruf10 on March 15, 2010, 06:31:45 PMshfi.hIcon will store the handle ?? isn't it ??
any working module ??
The example that I've post in your other thread about SHGetFileInfo() use this handle for showing icons. This icon is from the System image list! - you don't need to extract it from shell32.dll or any other file.
FPU in a trice: SmplMath
It's that simple!

donkey

Hi,

To find the exact file the icon originally came from when it was cached as well as the index in that file you have to use registry functions not shell functions. File extensions that have a particular icon are registered in HKEY_CLASSES_ROOT, you have only to read the key for the extension. For example .TXT files are registered in HKEY_CLASSES_ROOT as follows:

[HKEY_CLASSES_ROOT\.txt]
@="txtfile"
"Content Type"="text/plain"
"PerceivedType"="text"

[HKEY_CLASSES_ROOT\.txt\OpenWithProgIDs]
"opendocument.CalcDocument.1"=""
"opendocument.WriterDocument.1"=""

[HKEY_CLASSES_ROOT\.txt\PersistentHandler]
@="{5e941d80-bf96-11cd-b579-08002b30bfeb}"

[HKEY_CLASSES_ROOT\.txt\ShellNew]
"ItemName"=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,\
  6f,00,74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,\
  00,6e,00,6f,00,74,00,65,00,70,00,61,00,64,00,2e,00,65,00,78,00,65,00,2c,00,\
  2d,00,34,00,37,00,30,00,00,00
"NullFile"=""


As you can see the default for the main key is txtfile this is the key where you will find the information for the icon. So in the key (still HKEY_CLASSES_ROOT) txtfile you find the following:

[HKEY_CLASSES_ROOT\txtfile]
"EditFlags"=dword:00010000
@="Text Document"
"FriendlyTypeName"=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,\
  00,6f,00,6f,00,74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,\
  32,00,5c,00,6e,00,6f,00,74,00,65,00,70,00,61,00,64,00,2e,00,65,00,78,00,65,\
  00,2c,00,2d,00,34,00,36,00,39,00,00,00

[HKEY_CLASSES_ROOT\txtfile\DefaultIcon]
@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\
  00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,69,00,6d,00,\
  61,00,67,00,65,00,72,00,65,00,73,00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,31,\
  00,30,00,32,00,00,00
.....


There is more information but I have truncated it at DefaultIcon. Though the data type is HEX, it is actually an ascii string...

%SystemRoot%\system32\imageres.dll,-102

So the icon file for it is imageres.dll and it is icon group index number 102.

This is a quick and dirty way to read a lot of Windows preregistered types, it will not work with every file but using regedit and a bit of tweaking you can probably get it to work with everything:

GetIconFileName FRAME pExtension, pIconLocation
LOCAL hRegKey:%HANDLE
LOCAL cbRead:%DWORD32
LOCAL MainKey[256]:%TCHAR
LOCAL DefIcon[MAX_PATH]:%TCHAR

invoke RegOpenKeyEx,HKEY_CLASSES_ROOT,[pExtension],REG_OPTION_NON_VOLATILE,KEY_READ,ADDR hRegKey
test eax,eax
jz >
ret
:

mov D[cbRead],256
invoke RegQueryValueEx,[hRegKey],"",0,NULL,OFFSET MainKey,ADDR cbRead

test eax,eax
jnz >>.ERROR
cmp D[cbRead],0
je >>.ERROR
invoke RegCloseKey,[hRegKey]

invoke PathAppend,OFFSET MainKey,"DefaultIcon"

invoke RegOpenKeyEx,HKEY_CLASSES_ROOT,OFFSET MainKey,REG_OPTION_NON_VOLATILE,KEY_READ,ADDR hRegKey
test eax,eax
jz >
ret
:
mov D[cbRead],MAX_PATH
invoke RegQueryValueEx,[hRegKey],"",0,NULL,OFFSET DefIcon,ADDR cbRead
test eax,eax
jnz >>.ERROR
invoke RegCloseKey,[hRegKey]
invoke ExpandEnvironmentStrings,OFFSET DefIcon,[pIconLocation],MAX_PATH
xor eax,eax
ret

.ERROR
invoke RegCloseKey,[hRegKey]
xor eax,eax
dec eax
RET
ENDF


Since I only code in GoAsm, it is in that syntax but you should be able to translate it without much effort. Pass a pointer to the extension in the form ".txt" to the function and a pointer to a buffer (usually MAX_PATH size) and it will return the entry for the icon in the buffer. Returns ERROR_SUCCESS if the information was found otherwise a non-zero value.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

maruf10

some simple queries  ....

if i want to see the system index number of icon of vlc.exe(e.g path : D:\VideoLAN\VLC\vlc.exe) and firefox.exe(e.g path : D:\Mozilla Firefox\firefox.exe) what will be the value of pIconLocation and pExtension...??

which variable will return the index number ??<output will not be the same i hope :( >

what is "FRAME" in first line ??

as i am using xp there is no imageres.dll file in system32<i have to use shell32.dll>

donkey

The snippet will get the information for a file extension, executables have no registered icon since it is in the files resource section, so vlc.exe or Firefox.exe would use their own  icons. One of the file types registered to Firefox is .HTM so you would pass a pointer to that in pExtension, pIconLocation is a buffer of the size MAX_PATH that on exit will contain the library in which to find the icon and it's index number or the index number of the RT_GROUP_ICON it is selected from. In the case of group icons  (RT_GROUP_ICON) the index will be negative, in the case of normal icons (RT_ICON) it will be positive.

FRAME in GoAsm is equivalent to PROC in MASM.

GetIconFileName PROC pExtension:DWORD, pIconLocation:DWORD
LOCAL hRegKey:DWORD
LOCAL cbRead:DWORD
LOCAL MainKey[256]:BYTE
LOCAL DefIcon[MAX_PATH]:BYTE
LOCAL NullString:DWORD

.DATA
DefKeyName DB "DefaultIcon",0
.CODE

mov [NullString],0

invoke RegOpenKeyEx,HKEY_CLASSES_ROOT,[pExtension],REG_OPTION_NON_VOLATILE,KEY_READ,ADDR hRegKey
test eax,eax
jz @F
ret
@@:

mov [cbRead],256
invoke RegQueryValueEx,[hRegKey],ADDR NullString,0,NULL,ADDR MainKey,ADDR cbRead

test eax,eax
jnz ERROR0
cmp [cbRead],0
je ERROR0
invoke RegCloseKey,[hRegKey]

invoke PathAppend,ADDR MainKey,ADDR DefKeyName

invoke RegOpenKeyEx,HKEY_CLASSES_ROOT,ADDR MainKey,REG_OPTION_NON_VOLATILE,KEY_READ,ADDR hRegKey
test eax,eax
jz @F
ret
@@:
mov [cbRead],MAX_PATH
invoke RegQueryValueEx,[hRegKey],ADDR NullString,0,NULL,ADDR DefIcon,ADDR cbRead
test eax,eax
jnz ERROR0
invoke RegCloseKey,[hRegKey]
invoke ExpandEnvironmentStrings,ADDR DefIcon,[pIconLocation],MAX_PATH
xor eax,eax
ret

ERROR0:
invoke RegCloseKey,[hRegKey]
xor eax,eax
dec eax
RET
GetIconFileName ENDP


Be sure to include the following:

include \Programming\masm32\include\masm32rt.inc
.686
include \Programming\masm32\include\advapi32.inc
includelib \Programming\masm32\lib\advapi32.lib
include \Programming\masm32\include\shlwapi.inc
includelib \Programming\masm32\lib\shlwapi.lib


Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

maruf10

Thanks for your continuous help ..

my actual problem is :
  i have listed all .exe file paths of a drive . now i will check their icon . if any icon is like a "file folder" then without considering anything i want to delete that .exe file .... e.g :NewFolder.exe which is a virus file

:red <sorry to say i have not tested your code yet ... i am bit busy for my on going exam... :(l>...will your snippent be helpful for this purpose ?  :red

i have only the file path of an .exe file to test its icon ...
you have said to use .htm extension for firefox.exe..... but there is no info in my hand to use it ....

i have attached a SysImg.exe file . It shows 3 for "file folder" icon ...
so if any .exe files system icon index is "3" i will delete it ...
is my approach correct ??


N.B: Thanks for converting that code to masm32 . It will save lots of my time :)

maruf10

Edger ........
Where are you ?? ......... bump

donkey

Quote from: maruf10 on March 20, 2010, 12:00:22 PM
Edger ........
Where are you ?? ......... bump


Sorry, a bit busy with some of my own projects, I will try to take a look at it today.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

maruf10

Thanks ...
Just help me to identify  .exe files having "file folder" icon ....
i have the paths of all .exe file ...