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