// LnkIconShlExt.cpp : Implementation of CLnkIconShlExt
#include "stdafx.h"
#include "resource.h"
#include "LnkFileIcons.h"
#include "LnkIconShlExt.h"

/////////////////////////////////////////////////////////////////////////////
// CLnkIconShlExt

/*
********** METHOD 1 **********
This method returns a filename/index pair to the shell, telling it where the
icon is.  This is the easier way, but it requires you to keep track of the
resource IDs of the icons *and* keep them in the right order!
*/
STDMETHODIMP CLnkIconShlExt::GetIconLocation (
    UINT uFlags,  LPTSTR szIconFile, UINT cchMax,
    int* piIndex, UINT* pwFlags )
{
	// pwFlags is set to zero to get the default behavior from Explorer.  You 
    // can set it to GIL_SIMULATEDOC to have Explorer put the icon we return in
    // a "dog-eared paper" icon, and use _that_ as the icon for the file.
    //*pwFlags = GIL_SIMULATEDOC;
    *pwFlags = 0;

	if (uFlags & GIL_DEFAULTICON) return S_FALSE;

    HRESULT hres; 
	HRESULT result; 
    IShellLink* psl; 

	result = S_FALSE;
 
    // Get a pointer to the IShellLink interface. 
    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 
                            IID_IShellLink, (LPVOID*)&psl); 
    if (SUCCEEDED(hres)) 
    { 
        IPersistFile* ppf; 
 
        // Get a pointer to the IPersistFile interface. 
        hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); 
		
        if (SUCCEEDED(hres)) 
        { 
            // WCHAR wsz[MAX_PATH]; 
 
            // Ensure that the string is Unicode. 
            // MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz, MAX_PATH); 
 
            // Add code here to check return value from MultiByteWideChar 
            // for success.
 
            // Load the shortcut. 
            // hres = ppf->Load(wsz, STGM_READ); 
			USES_CONVERSION;
			hres = ppf->Load(T2OLE(m_szFilename), STGM_READ); 
			
            
            if (SUCCEEDED(hres)) 
            { 
                    // Get the path to the link target. 
					hres = psl->GetIconLocation(szIconFile, cchMax, piIndex);

                    if (SUCCEEDED(hres) && _tcslen(szIconFile)) 
                    { 
						result = S_OK;
					} else {
						*piIndex = 0;
						hres = psl->GetPath(szIconFile, cchMax, NULL, 0);
						if (SUCCEEDED(hres)) {
							DWORD tmp;
							if (GetBinaryType(szIconFile, &tmp)) {
								result = S_OK;
							} else {
								SHFILEINFO finfo;
								if (SHGetFileInfo(szIconFile, 0, &finfo, sizeof(finfo), SHGFI_ICONLOCATION)) {
									_tcscpy_s(szIconFile, cchMax, finfo.szDisplayName);
									*piIndex = finfo.iIcon;
									result = S_OK;
								}
							}
						}
					}
            } 

            // Release the pointer to the IPersistFile interface. 
            ppf->Release(); 
        } 

        // Release the pointer to the IShellLink interface. 
        psl->Release(); 
    } 
    return result; 

}

STDMETHODIMP CLnkIconShlExt::Extract (
    LPCTSTR pszFile, UINT nIconIndex, HICON* phiconLarge, HICON* phiconSmall,
    UINT nIconSize )
{
    return S_FALSE;                     // Tell the shell to do the extracting itself.
}

/*
********** METHOD 2 **********
This method stores the file size in the CLnkIconShlExt object, and does the
icon extraction manually.  This way is more complicated, but I prefer it since
you don't have to do bookkeeping of your resource IDs.
*/
/*
STDMETHODIMP CLnkIconShlExt::GetIconLocation (
    UINT uFlags,  LPTSTR szIconFile, UINT cchMax,
    int* piIndex, UINT* pwFlags )
{
DWORD  dwFileSizeLo, dwFileSizeHi;
HANDLE hFile;

    hFile = CreateFile ( m_szFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );

    if ( INVALID_HANDLE_VALUE == hFile )
        return S_FALSE;                 // tell the shell to use a default icon

    dwFileSizeLo = GetFileSize ( hFile, &dwFileSizeHi );

    CloseHandle ( hFile );

    if ( (DWORD) -1 == dwFileSizeLo && GetLastError() != NO_ERROR )
        return S_FALSE;                 // tell the shell to use a default icon

    m_qwFileSize = ((DWORDLONG) dwFileSizeHi)<<32 | dwFileSizeLo;

    // Tell the shell not to look at the name/index, and don't check the icon
    // cache.  Note that the GIL_NOTFILENAME flag doesn't really have any effect;
    // if we fill in szIconFile/piIndex, Explorer will still check them against
    // the cache.  So the only flag that's really important is GIL_DONTCACHE.
    *pwFlags = GIL_NOTFILENAME | GIL_DONTCACHE;

    return S_OK;
}

STDMETHODIMP CLnkIconShlExt::Extract (
    LPCTSTR pszFile, UINT nIconIndex, HICON* phiconLarge, HICON* phiconSmall,
    UINT nIconSize )
{
UINT uIconID;
WORD wSmallIconSize = HIWORD(nIconSize), wLargeIconSize = LOWORD(nIconSize);

    // Determine which icon to use, depending on the file size.
    if ( 0 == m_qwFileSize )
        uIconID = IDI_ZERO_BYTES;
    else if ( m_qwFileSize < 4096 )
        uIconID = IDI_UNDER_4K;
    else if ( m_qwFileSize < 8192 )
        uIconID = IDI_UNDER_8K;
    else 
        uIconID = IDI_OVER_8K;

    // Load the icons!  The docs say that either HICON* param may be NULL,
    // so we have to check for that case.
    if ( NULL != phiconLarge )
        {
        *phiconLarge = (HICON) LoadImage ( _Module.GetResourceInstance(),
                                           MAKEINTRESOURCE(uIconID), IMAGE_ICON,
                                           wLargeIconSize, wLargeIconSize,
                                           LR_DEFAULTCOLOR );
        }

    if ( NULL != phiconSmall )
        {
        *phiconSmall = (HICON) LoadImage ( _Module.GetResourceInstance(),
                                           MAKEINTRESOURCE(uIconID), IMAGE_ICON,
                                           wSmallIconSize, wSmallIconSize,
                                           LR_DEFAULTCOLOR );
        }

    return S_OK;
}
*/
