diff --git a/Pilz.Win32/Internals/IconExtractor.vb b/Pilz.Win32/Internals/IconExtractor.vb
index d6487b9..1411abe 100644
--- a/Pilz.Win32/Internals/IconExtractor.vb
+++ b/Pilz.Win32/Internals/IconExtractor.vb
@@ -1,5 +1,7 @@
Imports System.Drawing
Imports System.Runtime.InteropServices
+
+Imports Pilz.Win32.Mapped
Imports Pilz.Win32.Native
Namespace Internals
@@ -10,10 +12,11 @@ Namespace Internals
''' Extrahiert das Icon aus einer Datei oder aus einem Ordner.
'''
''' Hier übergeben Sie den Pfad der Datei von dem das Icon extrahiert werden soll.
- ''' Bei übergabe von true wird ein kleines und bei false ein großes Icon zurück gegeben.
- Public Shared Function ExtractIcon(FilePath As String, Small As Boolean) As Icon
+ ''' Bei übergabe von true wird ein kleines und bei false ein großes Icon zurück gegeben.
+ Public Shared Function ExtractIcon(FilePath As String, size As SystemIconSize) As Icon
Dim icon As Icon
Dim shinfo As New SHFILEINFO
+ Dim small As Boolean = size = SystemIconSize.Small
LibShell32.SHGetFileInfo(FilePath, 0, shinfo, Math.Truncate(Marshal.SizeOf(shinfo)), SHFILEINFO.SHGFI_ICON Or If(Small, SHFILEINFO.SHGFI_SMALLICON, SHFILEINFO.SHGFI_LARGEICON))
diff --git a/Pilz.Win32/Internals/IconFactory.vb b/Pilz.Win32/Internals/IconFactory.vb
new file mode 100644
index 0000000..26ff50f
--- /dev/null
+++ b/Pilz.Win32/Internals/IconFactory.vb
@@ -0,0 +1,208 @@
+Imports System
+Imports System.Runtime.InteropServices
+Imports Microsoft.Win32
+Imports System.Reflection
+Imports System.Collections.Generic
+Imports System.Drawing
+Imports Pilz.Win32.Native
+Imports Pilz.Win32.Native.Shell32
+Imports Pilz.Win32.Mapped
+
+Namespace Internals
+ Public Class IconFactory
+
+#Region "Custom exceptions class"
+
+ Public Class IconNotFoundException
+ Inherits Exception
+ Public Sub New(ByVal fileName As String, ByVal index As Integer)
+ MyBase.New(String.Format("Icon with Id = {0} wasn't found in file {1}", index, fileName))
+ End Sub
+ End Class
+
+ Public Class UnableToExtractIconsException
+ Inherits Exception
+ Public Sub New(ByVal fileName As String, ByVal firstIconIndex As Integer, ByVal iconCount As Integer)
+ MyBase.New(String.Format("Tryed to extract {2} icons starting from the one with id {1} from the ""{0}"" file but failed", fileName, firstIconIndex, iconCount))
+ End Sub
+ End Class
+
+#End Region
+
+
+ '''
+ ''' Get the number of icons in the specified file.
+ '''
+ ''' Full path of the file to look for.
+ '''
+ Private Shared Function GetIconsCountInFile(fileName As String) As Integer
+ Return ExtractIconEx(fileName, -1, Nothing, Nothing, 0)
+ End Function
+
+#Region "ExtractIcon-like functions"
+
+ Public Shared Sub ExtractEx(ByVal fileName As String, ByVal largeIcons As List(Of Icon), ByVal smallIcons As List(Of Icon), ByVal firstIconIndex As Integer, ByVal iconCount As Integer)
+ '
+ ' Memory allocations
+ '
+
+ Dim smallIconsPtrs As IntPtr() = Nothing
+ Dim largeIconsPtrs As IntPtr() = Nothing
+
+ If smallIcons IsNot Nothing Then
+ smallIconsPtrs = New IntPtr(iconCount - 1) {}
+ End If
+ If largeIcons IsNot Nothing Then
+ largeIconsPtrs = New IntPtr(iconCount - 1) {}
+ End If
+
+ '
+ ' Call to native Win32 API
+ '
+
+ Dim apiResult = ExtractIconEx(fileName, firstIconIndex, largeIconsPtrs, smallIconsPtrs, iconCount)
+ If apiResult <> iconCount Then
+ Throw New UnableToExtractIconsException(fileName, firstIconIndex, iconCount)
+ End If
+
+ '
+ ' Fill lists
+ '
+
+ If smallIcons IsNot Nothing Then
+ smallIcons.Clear()
+ For Each actualIconPtr In smallIconsPtrs
+ smallIcons.Add(Icon.FromHandle(actualIconPtr))
+ Next
+ End If
+ If largeIcons IsNot Nothing Then
+ largeIcons.Clear()
+ For Each actualIconPtr In largeIconsPtrs
+ largeIcons.Add(Icon.FromHandle(actualIconPtr))
+ Next
+ End If
+ End Sub
+
+ Public Shared Function ExtractEx(ByVal fileName As String, ByVal size As SystemIconSize, ByVal firstIconIndex As Integer, ByVal iconCount As Integer) As List(Of Icon)
+ Dim iconList As New List(Of Icon)()
+
+ Select Case size
+ Case SystemIconSize.Large
+ ExtractEx(fileName, iconList, Nothing, firstIconIndex, iconCount)
+ Case SystemIconSize.Small
+ ExtractEx(fileName, Nothing, iconList, firstIconIndex, iconCount)
+ Case Else
+ Throw New ArgumentOutOfRangeException("size")
+ End Select
+
+ Return iconList
+ End Function
+
+ Public Shared Sub Extract(ByVal fileName As String, ByVal largeIcons As List(Of Icon), ByVal smallIcons As List(Of Icon))
+ Dim iconCount = GetIconsCountInFile(fileName)
+ ExtractEx(fileName, largeIcons, smallIcons, 0, iconCount)
+ End Sub
+
+ Public Shared Function Extract(ByVal fileName As String, ByVal size As SystemIconSize) As List(Of Icon)
+ Dim iconCount = GetIconsCountInFile(fileName)
+ Return ExtractEx(fileName, size, 0, iconCount)
+ End Function
+
+ Public Shared Function ExtractOne(ByVal fileName As String, ByVal index As Integer, ByVal size As SystemIconSize) As Icon
+ Try
+ Dim iconList = ExtractEx(fileName, size, index, 1)
+ Return iconList(0)
+ Catch __unusedUnableToExtractIconsException1__ As UnableToExtractIconsException
+ Throw New IconNotFoundException(fileName, index)
+ End Try
+ End Function
+
+ Public shared Sub ExtractOne(ByVal fileName As String, ByVal index As Integer, ByRef largeIcon As Icon, ByRef smallIcon As Icon)
+ Dim smallIconList As List(Of Icon) = New List(Of Icon)()
+ Dim largeIconList As List(Of Icon) = New List(Of Icon)()
+ Try
+ ExtractEx(fileName, largeIconList, smallIconList, index, 1)
+ largeIcon = largeIconList(0)
+ smallIcon = smallIconList(0)
+ Catch __unusedUnableToExtractIconsException1__ As UnableToExtractIconsException
+ Throw New IconNotFoundException(fileName, index)
+ End Try
+ End Sub
+
+#End Region
+
+ 'this will look throw the registry
+ 'to find if the Extension have an icon.
+ Public Shared Function IconFromExtension(ByVal extension As String, ByVal size As SystemIconSize) As Icon
+ ' Add the '.' to the extension if needed
+ If extension(0) <> "."c Then extension = "."c & extension
+
+ 'opens the registry for the wanted key.
+ Dim Root = Registry.ClassesRoot
+ Dim ExtensionKey = Root.OpenSubKey(extension)
+ ExtensionKey.GetValueNames()
+ Dim ApplicationKey As RegistryKey = Root.OpenSubKey(ExtensionKey.GetValue("").ToString())
+
+ 'gets the name of the file that have the icon.
+ Dim IconLocation As String = ApplicationKey.OpenSubKey("DefaultIcon").GetValue("").ToString()
+ Dim IconPath = IconLocation.Split(","c)
+
+ If Equals(IconPath(1), Nothing) Then IconPath(1) = "0"
+ Dim Large = New IntPtr(0) {}, Small = New IntPtr(0) {}
+
+ 'extracts the icon from the file.
+ ExtractIconEx(IconPath(0), Convert.ToInt16(IconPath(1)), Large, Small, 1)
+ Return If(size = SystemIconSize.Large, Icon.FromHandle(Large(0)), Icon.FromHandle(Small(0)))
+ End Function
+
+ Public Shared Function IconFromExtensionShell(ByVal extension As String, ByVal size As SystemIconSize) As Icon
+ 'add '.' if nessesry
+ If extension(0) <> "."c Then extension = "."c & extension
+
+ 'temp struct for getting file shell info
+ Dim fileInfo As SHFILEINFO = New SHFILEINFO()
+
+ SHGetFileInfo(extension, 0, fileInfo, Marshal.SizeOf(fileInfo), FileInfoFlags.SHGFI_ICON Or FileInfoFlags.SHGFI_USEFILEATTRIBUTES Or CType(size, FileInfoFlags))
+
+ Return Icon.FromHandle(fileInfo.hIcon)
+ End Function
+
+ Public Shared Function IconFromResource(ByVal resourceName As String) As Icon
+ Dim assembly As Assembly = Assembly.GetCallingAssembly()
+
+ Return New Icon(assembly.GetManifestResourceStream(resourceName))
+ End Function
+
+ '''
+ ''' Parse strings in registry who contains the name of the icon and
+ ''' the index of the icon an return both parts.
+ '''
+ ''' The full string in the form "path,index" as found in registry.
+ ''' The "path" part of the string.
+ ''' The "index" part of the string.
+ Public Shared Sub ExtractInformationsFromRegistryString(ByVal regString As String, ByRef fileName As String, ByRef index As Integer)
+ If Equals(regString, Nothing) Then
+ Throw New ArgumentNullException("regString")
+ End If
+ If regString.Length = 0 Then
+ Throw New ArgumentException("The string should not be empty.", "regString")
+ End If
+
+ index = 0
+ Dim strArr = regString.Replace("""", "").Split(","c)
+ fileName = strArr(0).Trim()
+ If strArr.Length > 1 Then
+ Call Integer.TryParse(strArr(1).Trim(), index)
+ End If
+ End Sub
+
+ Public Shared Function ExtractFromRegistryString(ByVal regString As String, ByVal size As SystemIconSize) As Icon
+ Dim fileName As String
+ Dim index As Integer
+ ExtractInformationsFromRegistryString(regString, fileName, index)
+ Return ExtractOne(fileName, index, size)
+ End Function
+
+ End Class
+
+End Namespace
diff --git a/Pilz.Win32/Mapped/IconExtractor.vb b/Pilz.Win32/Mapped/IconExtractor.vb
new file mode 100644
index 0000000..c244ec4
--- /dev/null
+++ b/Pilz.Win32/Mapped/IconExtractor.vb
@@ -0,0 +1,17 @@
+Imports System.Drawing
+
+Namespace Mapped
+
+ Public Module IconExtractor
+
+ Public Function ExtractIconFromFilePath(filePath As String, size As SystemIconSize) As Icon
+ Return Internals.IconExtractor.ExtractIcon(filePath, size)
+ End Function
+
+ Public Function ExtractIconFromFileExtension(fileExtension As String, size As SystemIconSize)
+ Return Internals.IconFactory.IconFromExtensionShell(fileExtension, size)
+ End Function
+
+ End Module
+
+End Namespace
diff --git a/Pilz.Win32/Mapped/SystemIconSize.vb b/Pilz.Win32/Mapped/SystemIconSize.vb
new file mode 100644
index 0000000..99bd177
--- /dev/null
+++ b/Pilz.Win32/Mapped/SystemIconSize.vb
@@ -0,0 +1,12 @@
+Namespace Mapped
+
+ '''
+ ''' Two constants extracted from the FileInfoFlags, the only that are
+ ''' meaningfull for the user of this class.
+ '''
+ Public Enum SystemIconSize As Integer
+ Large
+ Small
+ End Enum
+
+End Namespace
diff --git a/Pilz.Win32/Native/FileInfoFlags.vb b/Pilz.Win32/Native/FileInfoFlags.vb
new file mode 100644
index 0000000..120f982
--- /dev/null
+++ b/Pilz.Win32/Native/FileInfoFlags.vb
@@ -0,0 +1,20 @@
+Namespace Native
+
+
+ Public Enum FileInfoFlags As Integer
+ '''
+ ''' Retrieve the handle to the icon that represents the file and the index
+ ''' of the icon within the system image list. The handle is copied to the
+ ''' hIcon member of the structure specified by psfi, and the index is copied
+ ''' to the iIcon member.
+ '''
+ SHGFI_ICON = &H100
+ '''
+ ''' Indicates that the function should not attempt to access the file
+ ''' specified by pszPath. Rather, it should act as if the file specified by
+ ''' pszPath exists with the file attributes passed in dwFileAttributes.
+ '''
+ SHGFI_USEFILEATTRIBUTES = &H10
+ End Enum
+
+End Namespace
\ No newline at end of file
diff --git a/Pilz.Win32/Native/SHFILEINFO.vb b/Pilz.Win32/Native/SHFILEINFO.vb
index 2cd55f8..3717b55 100644
--- a/Pilz.Win32/Native/SHFILEINFO.vb
+++ b/Pilz.Win32/Native/SHFILEINFO.vb
@@ -2,18 +2,43 @@
Namespace Native
-
+ '''
+ ''' Contains information about a file object.
+ '''
Public Structure SHFILEINFO
Public Const SHGFI_ICON As UInteger = &H100
Public Const SHGFI_LARGEICON As UInteger = &H0
Public Const SHGFI_SMALLICON As UInteger = &H1
-
+ '''
+ ''' Handle to the icon that represents the file. You are responsible for
+ ''' destroying this handle with DestroyIcon when you no longer need it.
+ '''
Public hIcon As IntPtr
+
+ '''
+ ''' Index of the icon image within the system image list.
+ '''
Public iIcon As IntPtr
+
+ '''
+ ''' Array of values that indicates the attributes of the file object.
+ ''' For information about these values, see the IShellFolder::GetAttributesOf
+ ''' method.
+ '''
Public dwAttributes As UInteger
+
+ '''
+ ''' String that contains the name of the file as it appears in the Microsoft
+ ''' Windows Shell, or the path and file name of the file that contains the
+ ''' icon representing the file.
+ '''
Public szDisplayName As String
+
+ '''
+ ''' String that describes the type of file.
+ '''
Public szTypeName As String
End Structure
diff --git a/Pilz.Win32/Native/Shell32.vb b/Pilz.Win32/Native/Shell32.vb
new file mode 100644
index 0000000..f6595e1
--- /dev/null
+++ b/Pilz.Win32/Native/Shell32.vb
@@ -0,0 +1,70 @@
+Imports System.Runtime.InteropServices
+
+Namespace Native
+
+ Public Class Shell32
+
+ '''
+ ''' Creates an array of handles to large or small icons extracted from
+ ''' the specified executable file, dynamic-link library (DLL), or icon
+ ''' file.
+ '''
+ '''
+ ''' Name of an executable file, DLL, or icon file from which icons will
+ ''' be extracted.
+ '''
+ '''
+ '''
+ ''' Specifies the zero-based index of the first icon to extract. For
+ ''' example, if this value is zero, the function extracts the first
+ ''' icon in the specified file.
+ '''
+ '''
+ ''' If this value is �1 and and
+ ''' are both NULL, the function returns
+ ''' the total number of icons in the specified file. If the file is an
+ ''' executable file or DLL, the return value is the number of
+ ''' RT_GROUP_ICON resources. If the file is an .ico file, the return
+ ''' value is 1.
+ '''
+ '''
+ ''' Windows 95/98/Me, Windows NT 4.0 and later: If this value is a
+ ''' negative number and either or
+ ''' is not NULL, the function begins by
+ ''' extracting the icon whose resource identifier is equal to the
+ ''' absolute value of . For example, use -3
+ ''' to extract the icon whose resource identifier is 3.
+ '''
+ '''
+ '''
+ ''' An array of icon handles that receives handles to the large icons
+ ''' extracted from the file. If this parameter is NULL, no large icons
+ ''' are extracted from the file.
+ '''
+ '''
+ ''' An array of icon handles that receives handles to the small icons
+ ''' extracted from the file. If this parameter is NULL, no small icons
+ ''' are extracted from the file.
+ '''
+ '''
+ ''' Specifies the number of icons to extract from the file.
+ '''
+ '''
+ ''' If the parameter is -1, the
+ ''' parameter is NULL, and the
+ ''' parameter is NULL, then the return
+ ''' value is the number of icons contained in the specified file.
+ ''' Otherwise, the return value is the number of icons successfully
+ ''' extracted from the file.
+ '''
+
+ Public Shared Function ExtractIconEx( ByVal lpszFile As String, ByVal nIconIndex As Integer, ByVal phIconLarge As IntPtr(), ByVal phIconSmall As IntPtr(), ByVal nIcons As Integer) As Integer
+ End Function
+
+
+ Public Shared Function SHGetFileInfo(ByVal pszPath As String, ByVal dwFileAttributes As Integer, ByRef psfi As SHFILEINFO, ByVal cbFileInfo As Integer, ByVal uFlags As FileInfoFlags) As IntPtr
+ End Function
+
+ End Class
+
+End Namespace