🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #12414

Re: Failed to resolve explorer lnk from the taskbar

#12414
From: Angus
Date: Mon, 08 Dec 2003 02:40
262 lines
11085 bytes
Hi Remy, first many thanks for the revised code using com, and also the
great hints, especially the use of the struct.

With regard to the function itself, i'm afraid it still will not resolve the
Internet Explorer lnk file when opened via the taskbar, which on this
machine is at C:\Documents and Settings\Administrator\Application
Data\Microsoft\Internet Explorer\Quick Launch.
The filename comes back as null.

other lnk' s from the taskbar resolve without problems.
Any other thoughts on why this lnk file in particular doesn't work.

Again many thanks for your previous help. Angus.

Oh, and the com RAII (hope this is right) wrapper classes work a treat, to a
point there is now a small glimmer of light at the end of the COM tunnel.


"Remy Lebeau (TeamB)" <gambit47.no.spam@no.spam.yahoo.com> wrote in message
news:3fd2f996@newsgroups.borland.com...
>
> "Angus" <aguspickton@yahoo.com> wrote in message
> news:3fd298ae@newsgroups.borland.com...
> > But when applied to certain taskbar icons, such as
> > explorer, PathName comes out as NULL.
>
> You're going to have to be a little more specific. "explorer" could mean
> anything.  Are you referring to "Windows Explorer"?  "Internet Explorer"?
> "Some Other Explorer"?
>
> The issue is probably due the fact that not all desktop items are
shortcuts
> to begin with.  How exactly are you determining the initial filename for
the
> desktop items and then calling the ResolveDeskTopIcon function to begin
> with?  You didn't show any of that code at all.
>
> > bool MXMAPI::ResolveDeskTopIcon(HWND hwnd, LPCSTR
> > pszShortcutFile,AnsiString& FileName,AnsiString& PathName,
> > AnsiString& Arguments,AnsiString& Description, WORD& Hotkey,
> > AnsiString& IconPath,AnsiString& GetWorkingDirectory,int& IconIndex,
> > int& GetShowCommand){
>
> That is a lot of parameters for a function to have.  You should seriously
> consider storing the link information into a separate structure instead.
> That way, you can pass in just a single parameter for the structure
itself,
> rather than separate parameters for the individual values.  Not only does
> that make the code cleaner and easier to manage, but it also is much more
> flexible should you want to add more return values later on.  For example:
>
>     struct TLinkInfo
>     {
>         AnsiString FileName;
>         AnsiString PathName;
>         AnsiString Arguments;
>         AnsiString Description;
>         AnsiString IconPath;
>         AnsiString WorkingDir;
>         int IconIndex;
>         int ShowCommand;
>         WORD Hotkey;
>     };
>
>     bool MXMAPI::ResolveDeskTopIcon(HWND hwnd, LPCSTR pszShortcutFile,
> TListInfo &Info)
>     {
>         // fill in the Info parameter as needed..
>     }
>
> >   if(SUCCEEDED(CoInitialize(NULL))){
>
> I would suggest that you look at the TInitOle class in utilcls.h.  It will
> allow you to initialize *and release* COM in a safe manner, in case an
> exception occurs your current code would have a lot of leaks.
>
> >      IShellLink* psl;// Shell Link Interface
> >      IPersistFile *ppf; // Interface to Shortcut
>
> For the same reason above, I would suggest you look at the TComInterface
> wrapper class in utilcls.h as well.
>
> >             AnsiString FilePath(pszShortcutFile);
> >             wchar_t wFilePath[MAX_PATH];
> >             FilePath.WideChar(wFilePath, MAX_PATH);
>
> Rather than doing that, you could just use a WideString instead.  It will
> handle the char*->wchar_t* conversion for you.
>
> >       char filename[MAX_PATH];
>
> You should initialize such a buffer to MAX_PATH+1, to make sure that there
> is always room for a null-terminator even if the path happens to be
exactly
> MAX_PATH in length.  Its rare, but it is possible.  You should also zero
out
> the buffer contents prior to using it.
>
> >                        if(pidl){
> >                          delete pidl;
> >                          pidl = NULL;
> >                        }
>
> That is completely wrong.  The ITEMIDLIST was allocated by the Shell's
> memory allocator.  You can't simply 'delete' the memory, the 'delete'
> operator does not use the same memory manager as the Shell, thus the
> ITEMIDLIST memory will *not* be freed correctly.  You must use
> IMalloc::Free() or CoTaskMemFree() instead in order to free the memory
> correctly.
>
> >                    else throw Exception("Unable to resolve lnk
filename");
>
> By throwing your own exceptions, you are leaking *all* of your interface
> instances.  With the way you have your code set up, Release() will not be
> called if an exception is thrown.  Either use TComInterface as I mentioned
> above, or else you must change the way you are using your exception
> handling, in order to make sure that Release() is always called no matter
> what.
>
> >    ppf->Release();      // Release pointer to IPersistFile interface.
> >    psl->Release();    // Release pointer to IShellLink interface.
>
> You are calling Release() on the IPersistFile instance even if the call to
> QueryInterface() fails, thus you would be calling Release() on an invalid
> pointer.  You need to move that call to Release() inside the if() block
for
> the QueryInterface() result, not outside of the block.
>
> >  e.Message += "Error: -(ResolveIt) mxm";
>
> I do not recommend that you *ever* alter any of the properties of an
> Exception when you catch one.  Always copy the Exception's values to local
> variables and use those instead.
>
> >  Application->ShowException(&e);
>
> Likewise, I would not suggest using ShowException().  It displays a
default
> message box that contains no meaninful information at all about the error.
> You should display your own message box so that you can include more
> meaningful info about why the error occured, etc.
>
> With all of that said, try this code instead:
>
>     #include <utilcls.h>
>     #include <shellapi.h>
>
>     struct TLinkInfo
>     {
>         AnsiString FileName;
>         AnsiString PathName;
>         AnsiString Arguments;
>         AnsiString Description;
>         AnsiString IconPath;
>         AnsiString WorkingDir;
>         int IconIndex;
>         int ShowCommand;
>         WORD Hotkey;
>     };
>
>     bool MXMAPI::ResolveDeskTopIcon(HWND hwnd, LPCSTR pszShortcutFile,
> TLinkInfo &Info)
>     {
>         // initialize defaults
>         Info.FileName = "";
>         Info.PathName = "";
>         Info.Arguments = "";
>         Info.Description = "";
>         Info.IconPath = "";
>         Info.WorkingDir = "";
>         Info.IconIndex = -1;
>         Info.ShowCommand = 0;
>         Info.Hotkey = 0;
>
>         try
>         {
>             // Before creating our CoCreatInstance, we first must
initialise
> the com library!
>             TInitOle ole;
>             if( !ole )
>                 throw Exception("Unable to initialize COM");
>
>             // Get a pointer to the IShellLink interface.
>             TComInterface<IShellLink> psl;
>             if( FAILED(CoCreateInstance(CLSID_ShellLink, NULL,
> CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl)) )
>                 throw Exception("Unable to create IShellLink");
>
>             // Get a pointer to the IPersistFile interface.
>             TComInterface<IPersistFile> ppf;
>             if( FAILED(psl->QueryInterface(IID_IPersistFile,
> (LPVOID*)&ppf)) )
>                 throw Exception("Unable to request IPersistFile");
>
>             // use the IPersistFile::Load function to load the shortcut
>             if( FAILED(ppf->Load(WideString(pszShortcutFile),
STGM_READ)) )
>                 throw Exception("Unable to load IShellLink");
>
>             // use the IShellLink::Resolve function to resolve the link
>             if( FAILED(psl->Resolve(NULL, SLR_INVOKE_MSI | SLR_NOUPDATE |
> SLR_NO_UI)) )
>                 throw Exception("Unable to resolve IShellLink");
>
>             // get the path of the link's target
>             LPITEMIDLIST pidl = NULL;
>             if( SUCCEEDED(psl->GetIDList(&pidl)) )
>             {
>                 char buf[MAX_PATH+1] = {0};
>                 if( SHGetPathFromIDList(pidl, buf) )
>                 {
>                     Info.PathName = buf;
>                     Info.FileName = ExtractFileName(Info.PathName);
>                 }
>                 CoTaskMemFree(pidl);
>             }
>
>             if( Info.FileName.IsEmpty() )
>                 throw Exception("Unable to resolve lnk filename");
>
>             char desc[MAX_PATH+1] = {0};
>             if( FAILED(psl->GetDescription(desc, MAX_PATH)) )
>                 throw Exception("Unable to resolve lnk description");
>             Info.Description = desc;
>
>             char args[MAX_PATH+1] = {0};
>             if( FAILED(psl->GetArguments(args, MAX_PATH)) )
>                 throw Exception("Unable to resolve lnk Arguments");
>             Info.Arguments = args;
>
>             if( FAILED(psl->GetHotkey(&Info.Hotkey)) )
>                 throw Exception("Error:Unable to resolve lnk Hotkey");
>
>             char icon[MAX_PATH+1] = {0};
>             if( FAILED(psl->GetIconLocation(icon, MAX_PATH,
> &Info.IconIndex)) )
>                 throw Exception("Unable to resolve lnk IconLocation");
>             Info.IconPath = icon;
>
>             char workingdir[MAX_PATH+1] = {0};
>             if( FAILED(psl->GetArguments(workingdir, MAX_PATH)) )
>                 throw Exception("Unable to resolve lnk IconLocation");
>             Info.WorkingDir = workingdir;
>
>             if( FAILED(psl->GetShowCmd(&Info.ShowCommand)) )
>                 throw Exception("Unable to resolve lnk IconLocation");
>         }
>         catch(const Exception &e)
>         {
>             MessageBox(hwnd, e.Message.c_str(), "Messenger", MB_OK |
> MB_ICONERROR | MB_TOPMOST);
>             return false;
>         }
>         return true;
>     }
>
>
> Gambit
>
>
Technical Details
Message-ID: <3fd3e61d@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!fu-berlin.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail
References: <3fd298ae@newsgroups.borland.com> <3fd2f996@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 10cc67,ebe7a1f15ea83f48
X-Google-Attributes: gid10cc67,public
X-Google-ArrivalTime: 2003-12-07 19:09:20 PST
Reply-To: "Angus" <anguspickton@yahoo.com>
From: "Angus" <aguspickton@yahoo.com>
Newsgroups: borland.public.cppbuilder.nativeapi
References: <3fd298ae@newsgroups.borland.com> <3fd2f996@newsgroups.borland.com>
Subject: Re: Failed to resolve explorer lnk from the taskbar
Date: Mon, 8 Dec 2003 15:40:06 +1300
Lines: 264
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
NNTP-Posting-Host: 203.173.216.167
Message-ID: <3fd3e61d@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1070851613 203.173.216.167 (7 Dec 2003 18:46:53 -0700)
Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!fu-berlin.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail