00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00025 #include "plibc_private.h"
00026 
00027 #include <shlobj.h>
00028 #include <objbase.h>
00029 
00030 extern "C" {
00031 
00032 BOOL _plibc_CreateShortcut(const char *pszSrc, const char *pszDest)
00033 {
00034     
00035     IShellLink *pLink;
00036     IPersistFile *pFile;
00037     WCHAR *pwszDest;
00038     char *pszFileLnk;
00039     HRESULT hRes;
00040     
00041     CoInitialize(NULL);
00042     
00043     if ((strlen(pszSrc) > _MAX_PATH) || (strlen(pszDest) + 4 > _MAX_PATH))
00044     {
00045       CoUninitialize();
00046       errno = ENAMETOOLONG;
00047       
00048       return FALSE;
00049     }
00050     
00051     
00052     if (CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
00053         IID_IShellLink, (void **) &pLink) != S_OK)
00054     {
00055       CoUninitialize();
00056       errno = ESTALE;
00057       
00058       return FALSE;
00059     }
00060   
00061     
00062     pLink->SetPath(pszSrc);
00063   
00064     
00065     if (pLink->QueryInterface(IID_IPersistFile, (void **) &pFile) != S_OK)
00066     {
00067       free(pwszDest);
00068       pLink->Release();
00069       CoUninitialize();
00070       errno = ESTALE;
00071      
00072       return FALSE;
00073     }
00074 
00075     
00076     pszFileLnk = (char *) malloc(strlen(pszDest) + 5);
00077     sprintf(pszFileLnk, "%s.lnk", pszDest);
00078   
00079     
00080     pwszDest = (WCHAR *) malloc((_MAX_PATH + 5) * sizeof(WCHAR));
00081     MultiByteToWideChar(CP_ACP, 0, pszFileLnk, -1, pwszDest, _MAX_PATH);
00082     
00083     free(pszFileLnk);
00084     
00085     
00086     if (FAILED(hRes = pFile->Save((LPCOLESTR) pwszDest, TRUE)))
00087     {
00088       free(pwszDest);
00089       pLink->Release();
00090       pFile->Release();
00091       CoUninitialize();
00092       SetErrnoFromHRESULT(hRes);
00093   
00094       return FALSE;
00095     }
00096   
00097     free(pwszDest);
00098     
00099     pFile->Release();
00100     pLink->Release();
00101     CoUninitialize();
00102     errno = 0;
00103       
00104     return TRUE;
00105 }
00106 
00107 BOOL _plibc_DereferenceShortcut(char *pszShortcut)
00108 {
00109   IShellLink *pLink;
00110   IPersistFile *pFile;
00111   WCHAR *pwszShortcut;
00112   char *pszLnk;
00113   int iErr, iLen;
00114   HRESULT hRes;
00115   HANDLE hLink;
00116   char szTarget[_MAX_PATH + 1];
00117 
00118   if (! *pszShortcut)
00119     return TRUE;
00120 
00121   CoInitialize(NULL);
00122   szTarget[0] = 0;
00123   
00124   
00125   if (CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
00126       IID_IShellLink, (void **) &pLink) != S_OK)
00127   {
00128     CoUninitialize();
00129     errno = ESTALE;
00130     
00131     return FALSE;
00132   }
00133 
00134   
00135   if (pLink->QueryInterface(IID_IPersistFile, (void **) &pFile) != S_OK)
00136   {
00137     pLink->Release();
00138     CoUninitialize();
00139     errno = ESTALE;
00140     
00141     return FALSE;
00142   }
00143 
00144   pwszShortcut = (WCHAR *) malloc((_MAX_PATH + 1) * sizeof(WCHAR));
00145 
00146   
00147 
00148   iLen = strlen(pszShortcut);
00149   if (iLen > 4 && (strcmp(pszShortcut + iLen - 4, ".lnk") != 0))
00150   {
00151     HANDLE hLink;
00152     
00153     pszLnk = (char *) malloc(iLen + 5);
00154     sprintf(pszLnk, "%s.lnk", pszShortcut);
00155   }
00156   else
00157     pszLnk = strdup(pszShortcut);
00158 
00159   
00160   hLink = CreateFile(pszLnk, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
00161                    NULL, OPEN_EXISTING, 0, NULL);
00162   if (hLink == INVALID_HANDLE_VALUE)
00163   {
00164     free(pszLnk);
00165     SetErrnoFromWinError(GetLastError());
00166     
00167     if (errno == ENOENT)
00168     {
00169       
00170 
00171 
00172 
00173       
00174       if (GetFileAttributes(pszShortcut) & FILE_ATTRIBUTE_DIRECTORY)
00175       {
00176         errno = EINVAL;
00177         
00178         pLink->Release();
00179         pFile->Release();
00180         free(pwszShortcut);
00181         CoUninitialize();
00182         
00183         return FALSE;
00184       }
00185 
00186       pszLnk = strdup(pszShortcut);
00187       
00188       hLink = CreateFile(pszLnk, GENERIC_READ, FILE_SHARE_READ |
00189                 FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
00190       SetErrnoFromWinError(GetLastError());      
00191     }
00192     else
00193     {
00194       pLink->Release();
00195       pFile->Release();
00196       free(pwszShortcut);
00197       CoUninitialize();
00198       
00199       return FALSE; 
00200     }
00201   }
00202     
00203   MultiByteToWideChar(CP_ACP, 0, pszLnk, -1, pwszShortcut, _MAX_PATH);
00204   
00205   
00206   if (FAILED(hRes = pFile->Load((LPCOLESTR) pwszShortcut, STGM_READ)))
00207   {
00208     pLink->Release();
00209     pFile->Release();
00210     free(pwszShortcut);
00211     CoUninitialize();
00212     
00213     
00214 
00215 
00216     if (hRes == E_FAIL || hRes == E_ACCESSDENIED)
00217     {
00218       
00219       if (hLink != INVALID_HANDLE_VALUE)
00220       {
00221         DWORD dwRead;
00222         char pMagic[4] = {0, 0, 0, 0};
00223         
00224         ReadFile(hLink, pMagic, 4, &dwRead, NULL);
00225         if (memcmp(pMagic, "L\0\0\0", 4) == 0)
00226           SetErrnoFromHRESULT(hRes);
00227         else
00228           errno = EINVAL; 
00229       }
00230       
00231     }
00232     else
00233       SetErrnoFromHRESULT(hRes);
00234 
00235     free(pszLnk);
00236           
00237     CloseHandle(hLink);
00238     return FALSE;
00239   }
00240   
00241   CloseHandle(hLink);
00242   free(pszLnk);
00243   free(pwszShortcut);
00244   
00245   
00246   if (FAILED(hRes = pLink->GetPath(szTarget, _MAX_PATH, NULL, 0)))
00247   {
00248     pLink->Release();
00249     pFile->Release();
00250     CoUninitialize();
00251     
00252     if (hRes == E_FAIL)
00253       errno = EINVAL; 
00254     else
00255       SetErrnoFromHRESULT(hRes);
00256     
00257     return FALSE;
00258   }
00259 
00260   pFile->Release();
00261   pLink->Release();
00262   CoUninitialize();
00263   errno = 0;
00264   
00265   if (szTarget[0] != 0)
00266   {
00267         strcpy(pszShortcut, szTarget);
00268         return TRUE;
00269   }
00270   else
00271   {
00272     
00273     errno = EINVAL;
00274     return FALSE;
00275   }
00276 }
00277 
00281 int __win_deref(char *path)
00282 {
00283   int iDepth = 0;
00284 
00285   errno = 0;
00286 
00287   while (_plibc_DereferenceShortcut(path))
00288   {
00289     if (iDepth++ > 10)
00290     {
00291       errno = ELOOP;
00292       return -1;
00293     }
00294   }
00295 
00296   return errno ? -1 : 0;
00297 }
00298 
00299 } 
00300 
00301