I've been attempting to write code using COM on my Windows 7 computer with MingW and C++11. For some reason, I've been receiving SIGSEGV through my debugger in the DesktopShortcut::SetIcon function after I try to set it back to the old icon path I got from DesktopShortcut::GetIcon. I've tested COM::Assert and it has caught all unsuccessful COM calls, so I believe it to be an issue in how I handle the std::wstring class (particularly in the DesktopShortcut/Files classes). I'm new to C++ so I'm not always aware of object lifetimes and scopes. Here's the relevant code:

wmain:

Code:
int wmain( int argc, wchar_t * argv[] )
{
    const std::wstring ICON_FOLDER_PATH = std::wstring( Files::GetBasePath( argv[0], wcslen( argv[0] ) ) ) + L"Icons";
    Random random;


    std::vector<std::wstring> paths;


    auto lambda = [&]( std::wstring& path, const wchar_t * fileName ) -> bool
    {
        paths.emplace_back( path + fileName );
        return true;
    };


    try
    {
        Files::Enumerate( lambda, ICON_FOLDER_PATH );
        Desktop desktop( true );




        for ( auto& shortcut : desktop.GetShortcuts( ) )
            shortcut.SetIcon( random.GetElement<std::wstring>( paths ).c_str( ) );
    }
    catch ( const wchar_t * description )
    {
        std::wcerr << description << L"\n";
    }
    catch ( std::exception &e )
    {
        std::wcerr << e.what( ) << L"\n";
    }


    return 0;
}
Files.cpp
Code:
bool Files::EndsWith( std::wstring& s, std::wstring& sub )
{
    const size_t sLength = s.length( );
    const size_t subLength = sub.length( );


    if ( sLength >= subLength )
        return s.compare( sLength - subLength, subLength, sub ) == 0;


    return false;
}


void Files::Enumerate( std::function<bool(std::wstring&, const wchar_t * )> callback, std::wstring path, bool recurse )
{
    bool success = true;
    WIN32_FIND_DATA data = { 0 };


    if ( path[path.length( ) - 1] != L'\\' ) path += L"\\";
    HANDLE directory = FindFirstFile( ( path + L"*" ).c_str( ), &data );


    if ( ( success = ( directory != INVALID_HANDLE_VALUE ) ) )
    {
        do
        {
            if ( wcscmp( data.cFileName, L"." ) && wcscmp( data.cFileName, L".." ) )
            {
                if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
                {
                    if ( recurse )
                        Files::Enumerate( callback,  path + std::wstring( data.cFileName ), recurse );
                }
                else
                    if ( !callback( path, data.cFileName ) )
                        break;
            }
        } while ( FindNextFile( directory, &data ) );


        FindClose( directory );
    }


    if ( !success )
    {
        Error::Windows( );
        throw L"Files::Enumerate(): FindFirstFile";
    }
}


void Files::Enumerate( std::function<bool(std::wstring&, const wchar_t * )> callback, std::wstring path, std::wstring extension, bool recurse )
{
    auto lambda = [&]( std::wstring& path, const wchar_t * fileName ) -> bool
    {
        std::wstring name( fileName );
        if ( Files::EndsWith( name, extension ) )
            return callback( path, fileName );


        return true;
    };


    Files::Enumerate( lambda, path, recurse );
}


const wchar_t * Files::GetBasePath( wchar_t * buffer, size_t length )
{
    for ( size_t i = length - 1; buffer[i] != L'\\' && i >= 0; --i )
        buffer[i] = '\0';


    return buffer;
}
Desktop.cpp:

Code:
Desktop::Desktop( bool revert ) : EXTENSION( L".lnk" ), revert( revert )
{
    Com.Assert( SHGetKnownFolderPath( FOLDERID_Desktop, 0, nullptr, &path ), L"SHGetKnownFolderPath( FOLDERID_DESKTOP, ... )" );
}


const wchar_t * Desktop::GetPath( )
{
    return path;
}


std::vector<DesktopShortcut>& Desktop::GetShortcuts( )
{
    if ( !shortcuts.empty( ) )
        shortcuts.clear( );


    Files::Enumerate
    (
        [&]( std::wstring& filePath, const wchar_t * fileName ) -> bool
        {
            shortcuts.emplace_back( ( filePath + fileName ).c_str( ), revert );
            return true;
        },
        path,
        EXTENSION,
        false
    );


    return shortcuts;
}


Desktop::~Desktop( )
{
    CoTaskMemFree( path );
}
DesktopShortcut.cpp

Code:
DesktopShortcut::DesktopShortcut( const wchar_t * path, bool revert ) : revert( revert )
{
    ShellLink = ( IShellLinkW * )Com.GetObject( CLSID_ShellLink, IID_IShellLink );
    PersistFile = ( IPersistFile * )Com.GetInterface( ShellLink, IID_IPersistFile );


    Com.Assert( PersistFile->Load( path, 0 ), path );
    Com.Assert( ShellLink->Resolve( nullptr, SLR_NO_UI ),  L"ShellLink->Resolve" );


    std::wcout << path << L"\n";
    if ( revert );
        this->GetIcon( &oldIconPath, &oldIconIndex );
}


void DesktopShortcut::SetIcon( const wchar_t * path, int index )
{
    Com.Assert( ShellLink->SetIconLocation( path, index ), L"ShellLink->SetIconLocation" );
    this->Save( );
}


void DesktopShortcut::GetIcon( std::wstring ** path, int * index )
{
     *path = new std::wstring( MAX_PATH, '\0' );
     std::wcout << *path << L"\n";
     Com.Assert( ShellLink->GetIconLocation( &( **path )[0], MAX_PATH, index ), L"ShellLink->GetIconLocation" );
     std::wcout << ( **path ) << L"\n";
     ( *path )->resize( wcslen( ( *path )->c_str( ) ) );
     std::wcout << ( **path ) << L"\n";
}


void DesktopShortcut::GetIcon( std::wstring ** path )
{
    int foo = 0;
    this->GetIcon( path, &foo );
}


void DesktopShortcut::GetIcon( int& path )
{
    std::wstring ** foo = nullptr;
    this->GetIcon( foo, &path );
    delete foo;
}


void DesktopShortcut::Save( )
{
    Com.Assert( PersistFile->Save( nullptr, false ), L"PersistFile->Save" );
    PersistFile->SaveCompleted( nullptr );
}


DesktopShortcut::~DesktopShortcut( )
{
    if ( revert )
    {
        this->SetIcon( ( *oldIconPath ).c_str( ), oldIconIndex );
        delete oldIconPath;
    }
}
I get output such as the following before it crashes:

C:\Users\Chris\Desktop\CodeBlocks.lnk
0x3a84a0










C:\Users\Chris\Desktop\Eclipse Java Mars.lnk
0x3a7878










C:\Users\Chris\Desktop\Excel 2013.lnk
0x3a7ef8
Many thanks, OldManJenkins.