Announcement

Collapse
No announcement yet.

How to read link (.lnk) files?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to read link (.lnk) files?

    Has anybody been able to read .lnk files yet? According to POFFS2 many people have tried but no source has apparently been posted All I need to find out is what file the .lnk file is pointing to so I could probably write a neanderthal routine to scan for it but it'd be nice to do it the proper way if anybody knows how?


    ------------------
    -

  • #2
    I just took a look on a lnk file under Linux :-)
    It's binary but the path of the source file is
    in plain-text. But I think, there is a Windows
    API to get the path.

    ------------------
    E-Mail (home): mailto:[email protected][email protected]</A>
    E-Mail (work): mailto:[email protected][email protected]</A>

    Comment


    • #3
      I found some C and C++ source code to do exactly what Im after and it seems to do it "properly" (using Co* APIs) - http://sparksoft.363.net/Info/Info15.htm
      It seems fairly straightforward but still beyond my C translation abilities! so ill continue looking i think
      It's been a while since i've messed with that, but i dug up the following
      source code. it has been so long that i can't remember if this was the file
      i got working, so someone should test it out (i don't have time). however,
      it basically decodes the windows .lnk file format to find out what it is a
      shortcut to, and determines if that is a directory (i was going to write a
      unix type ln command using .lnk file formats.....). there are 2 files here.
      one is a c version, the other is a c++ version.... hope this helps....
      -donald murray
      Code:
      ============================================
      c version
      ============================================
      #include <windows.h>
      #include <windowsx.h>
      #include <objbase.h>
      #include <shlobj.h>
      #include <stdio.h>
      #include <initguid.h>
      #include <string.h>
      main(int ac, char *av[])
      {
      ishelllink *psl;
      hresult hres;
      win32_find_data wfd;
      char szgotpath[max_path];
      ipersistfile *ppf;
          if (ac != 2)
      {
      printf("syntax: ln <pathname>\n");
      return 0;
      }
          hres = coinitialize(null);
      if (!succeeded(hres))
      printf("could not open the com library\n");
          hres = cocreateinstance(&clsid_shelllink, null, clsctx_inproc_server,
      &iid_ishelllink, (lpvoid *)&psl);
      if (succeeded(hres))
      {
      hres = psl->lpvtbl->queryinterface(psl, &iid_ipersistfile, &ppf);
              if (succeeded(hres))
      {
      word wsz[max_path];
                  multibytetowidechar(cp_acp, 0, av[1], -1, wsz, max_path);
                  hres = ppf->lpvtbl->load(ppf, wsz, stgm_read);
      if (succeeded(hres))
      {
      hres = psl->lpvtbl->resolve(psl, 0, slr_any_match);
                      if (succeeded(hres))
      {
      strcpy(szgotpath, av[1]);
                         hres = psl->lpvtbl->getpath(psl, szgotpath, max_path,
      (win32_find_data *)&wfd, slgp_shortpath );
      if (!succeeded(hres))
      printf("getpath failed!\n");
                         printf("this points to %s\n", wfd.cfilename);
      if (wfd.dwfileattributes & file_attribute_directory)
      printf("this is a directory\n");
      }
      }
      else
      printf("ipersistfile load error\n");
      ppf->lpvtbl->release(ppf);
      }
      else
      printf("queryinterface error\n");
      psl->lpvtbl->release(psl);
      }
      else
      printf("cocreateinstance error - hres = %08x\n", hres);
      return 0;
      }
      ==================================
      c++ version
      ==================================
      #include <windowsx.h>
      #include <objbase.h>
      #include <shlobj.h>
      #include <stdio.h>
      #include <initguid.h>
      #include <stdlib.h>
      #include <io.h>
      #include <string.h>
      // this program should print out whether the file is a link and where it
      // points to and whether it is a directory or not.
      //
      main(int ac, char *av[])
      {
      if (ac != 2)
      {
      printf("syntax: ln <pathname>\n");
      return 0;
      }
          ishelllink *psl;                            // pointer to ishelllink i/f
      hresult hres;
      win32_find_data wfd;
      char szgotpath[max_path];
          // get pointer to the ishelllink interface.
          hres = cocreateinstance(clsid_shelllink, null, clsctx_inproc_server,
      iid_ishelllink, (lpvoid *)&psl);
          if (succeeded(hres))
      {
      // get pointer to the ipersistfile interface.
              ipersistfile *ppf;
      hres = psl->queryinterface(iid_ipersistfile, (lpvoid *)&ppf);
              if (succeeded(hres))
      {
      word wsz[max_path];
                  // ensure string is unicode.
      multibytetowidechar(cp_acp, 0, av[1], -1, wsz, max_path);
                  // load the shell link
      hres = ppf->load(wsz, stgm_read);
      if (succeeded(hres))
      {
      // resolve the link.
                      hres = psl->resolve(0, slr_any_match);
      //                  ^
      // using 0 instead -| of hwnd, as hwnd is only used if
      // interface needs to prompt for more information. should use
      // hwnd from current console in the long run.
                      if (succeeded(hres))
      {
      strcpy(szgotpath, av[1]);
                          hres = psl->getpath(szgotpath, max_path,
      (win32_find_data *)&wfd, slgp_shortpath );
      if (!succeeded(hres))
      printf("getpath failed!\n");
                          printf("this points to %s\n", wfd.cfilename);
      if (wfd.dwfileattributes & file_attribute_directory)
      printf("this is a directory\n");
      }
      }
      else
      printf("ipersistfile load error\n");
      ppf->release();
      }
      else
      printf("queryinterface error\n");
      psl->release();
      }
      else
      printf("cocreateinstance error - hres = %08x\n", hres);
      return 0;
      }

      ------------------
      -

      Comment


      • #4
        have a look at http://www.powerbasic.com/support/pb...ad.php?t=23774

        regards
        peter

        ------------------
        [email protected]
        www.dreammodel.dk

        Comment


        • #5
          Thanks very much, Semen just alerted me to that URL, thanks Semen, thanks Peter, and thanks to author-of-the-piece Florent Heyworth and George Bleck for his mods that code works beautifully and seems to be the right way to do this - saves me writing a pathetic hack with binary file access
          it escaped my POFFS searches because I was searching for link instead of shortcut... *duh*


          [This message has been edited by Wayne Diamond (edited June 25, 2001).]
          -

          Comment


          • #6
            Wayne,

            Just for fun I rewrote George Bleck's code. Here you have a
            OOP-version:

            Test Code:
            Code:
            #compile exe
            #dim all
            #register none
            #include "win32api.inc"
            #include "link.inc"
             
            function pbmain
             
                if LinkOpen("C:\PBDLL60\Projects\SendTo\RunGAMS.lnk") = 0 then
                    msgbox "Could not open link" : exit function
                end if		
              
                msgbox LinkGetFilePath,, "LinkGetFilePath"
                msgbox LinkGetWorkingDirectory,, "LinkGetWorkingDirectory"
                msgbox LinkGetArguments,, "LinkGetArguments"
             
                LinkClose
             
            end function
            Here is the include-file:
            Code:
            DECLARE FUNCTION CoInitialize Lib "ole32.dll" ALIAS "CoInitialize"( BYVAL pvReserved AS DWORD ) AS DWORD
            DECLARE FUNCTION CoCreateInstance Lib "ole32.dll" ALIAS "CoCreateInstance"( rclsid AS STRING * 16, BYVAL pUnkOuter AS ANY, BYVAL dwClsContext AS DWORD, riid AS STRING * 16, ppv AS DWORD ) AS DWORD
            DECLARE SUB CoUninitialize Lib "ole32.dll" ALIAS "CoUninitialize"
            DECLARE SUB CoTaskMemFree Lib "ole32.dll" ALIAS "CoTaskMemFree"( pv AS DWORD )
            DECLARE FUNCTION Sub1( p1 AS ANY ) AS DWORD
            DECLARE FUNCTION Sub2( p1 AS ANY, p2 AS ANY ) AS DWORD
            DECLARE FUNCTION Sub3( p1 AS ANY, p2 AS ANY, p3 AS ANY ) AS DWORD
            DECLARE FUNCTION Sub5( p1 AS ANY, p2 AS ANY, p3 AS ANY, p4 AS ANY, p5 AS ANY ) AS DWORD
              
            %LinkOpen = 1
            %LinkClose = 2
            %LinkGetFilePath = 3
            %LinkGetWorkingDirectory = 4
            %LinkGetArguments = 5
              
            function LinkMainFunction(byval func_id as long, byval s as string) as string
              
                LOCAL CLSCTX_INPROC_SERVER AS DWORD
                LOCAL CLSID_ShellLink AS STRING * 16
                LOCAL FileData AS WIN32_FIND_DATA
                LOCAL Flags AS DWORD
                LOCAL IID_IShellLink AS STRING * 16
                LOCAL IID_Persist AS STRING * 16
                LOCAL lResult AS DWORD
                LOCAL outvalue AS ASCIIZ * 128
                local pp AS DWORD PTR
                static ppf AS DWORD PTR
                static psl AS DWORD PTR
                LOCAL TmpAsciiz AS ASCIIZ * %MAX_PATH
                LOCAL TmpWide AS ASCIIZ * ( 2 * %MAX_PATH )
             
                select case func_id
                case %LinkOpen
            	CLSID_ShellLink = MKL$( &H00021401 ) + CHR$( 0, 0, 0, 0, &HC0, 0, 0, 0, 0, 0, 0, &H46 )
            	IID_IShellLink = MKL$( &H000214EE ) + CHR$( 0, 0, 0, 0, &HC0, 0, 0, 0, 0, 0, 0, &H46 )
            	IID_Persist = MKL$( &H0000010B ) + CHR$( 0, 0, 0, 0, &HC0, 0, 0, 0, 0, 0, 0, &H46 )
            	CLSCTX_INPROC_SERVER = 1
             
            	CoInitialize %Null
             
            	if CoCreateInstance( CLSID_ShellLink, %Null, CLSCTX_INPROC_SERVER, IID_IShellLink, psl ) <> %S_OK then
            	    function = "" : exit function
            	end if
              
            	pp = @psl: CALL DWORD @pp USING Sub3( BYVAL psl, IID_Persist, ppf ) TO lResult
            	TmpAsciiz = s
            	MultiByteToWideChar %CP_ACP, 0, TmpAsciiz, - 1, TmpWide, %MAX_PATH
            	pp = @ppf + 20: CALL DWORD @pp USING Sub3( BYVAL ppf, TmpWide, BYVAL %True )
             
            	function = "OK" : exit function
              
            	case %LinkClose
            	    'Release the persistant file
            	    pp = @ppf + 8: CALL DWORD @pp USING Sub1( BYVAL ppf )
            	    'Unbind the shell link object from the persistent file
            	    pp = @psl + 8: CALL DWORD @pp USING Sub1( BYVAL psl )
             
            	    CoUninitialize : exit function
             	
            	case %LinkGetFilePath
            	    pp = @psl + 12: CALL DWORD @pp USING Sub5( BYVAL psl, outvalue, BYVAL %MAX_PATH, FileData, Flags )	
            	    function = outvalue : exit function
             
            	case %LinkGetWorkingDirectory
            	    pp = @psl + 32: CALL DWORD @pp USING Sub3( BYVAL psl, outvalue, BYVAL %MAX_PATH )	
            	    function = outvalue : exit function
             
            	case %LinkGetArguments
            	    pp = @psl + 40: CALL DWORD @pp USING Sub3( BYVAL psl, outvalue, BYVAL %MAX_PATH )	
            	    function = outvalue : exit function
             
            	end select 
             
            end function
             
            function LinkOpen(byval LinkPath as string) as long
                if LinkMainFunction(%LinkOpen, LinkPath) = "" then exit function
                function = 1
            end function	
              
            sub LinkClose()
                LinkMainFunction %LinkClose, ""
            end sub
             
            function LinkGetFilePath() as string
                function = LinkMainFunction(%LinkGetFilePath, "")
            end function	
             
            function LinkGetWorkingDirectory() as string
                function = LinkMainFunction(%LinkGetWorkingDirectory, "")
            end function	
             
            function LinkGetArguments() as string
                function = LinkMainFunction(%LinkGetArguments, "")
            end function
            Regards
            Peter


            ------------------
            [email protected]
            www.dreammodel.dk

            Comment


            • #7
              I just checked out the source code in the forum that was re-written (Nice job both of you)...

              Question!


              We have need to look at a specific .LNK file to determine what the UNC name is inside the .LNK file.

              MS has a tool that does this, but seems like it would just be one more function to add, if so how do you do that?


              Reason I ask is that for some reason after a Dr watson that part gets changed, but you don't see that part unless you open the .LNK file with a hex editor...

              In other words if we dr watson ONE time our problems multiply exponentially because of that.
              So this code will help build a tool to validate the UNC name did not infact change...


              Thanks!


              Scott


              ------------------
              Scott
              Scott Turchin
              MCSE, MCP+I
              http://www.tngbbs.com
              ----------------------
              True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

              Comment

              Working...
              X