#include #include #include WCHAR *Convert(char *psz) { int c; WCHAR *pwsz = new WCHAR [ c = strlen(psz) + 1 ]; if (pwsz) mbstowcs(pwsz, psz, c); return pwsz; } #define CHECKNE(hr, stat, string, errRet) \ if (hr != stat) { iLine = __LINE__; pszErr = string; goto errRet; } HRESULT TouchFile(WCHAR *pwszSource) { FILETIME ftc; SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &ftc); return StgSetTimes(pwszSource, &ftc, NULL, NULL); } HRESULT CreateLink(WCHAR *pwszClient, WCHAR *pwszSource) { HRESULT hr; IBindCtx *pbc=NULL; ULONG ulEaten; IMoniker *pmkSource=NULL; IStorage *pstg=NULL; IOleObject *poo=NULL; IMoniker *pmkThis=NULL; IMoniker *pmkLink=NULL; IPersistStorage *pps=NULL; char *pszErr; int iLine=0; hr = CreateFileMoniker(pwszClient, &pmkThis); CHECKNE(hr, S_OK, "CreateFileMoniker", errRet); hr = CreateItemMoniker(L"!", L"Link", &pmkLink); CHECKNE(hr, S_OK, "CreateItemMoniker", errRet); hr = StgCreateDocfile(pwszClient, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pstg); CHECKNE(hr, S_OK, "StgCreateDocfile", errRet); hr = CreateBindCtx(0, &pbc); CHECKNE(hr, S_OK, "CreateBindCtx", errRet); hr = MkParseDisplayName(pbc, pwszSource, &ulEaten, &pmkSource); CHECKNE(hr, S_OK, "MkParseDisplayName", errRet); hr = OleCreateLink(pmkSource, IID_IOleObject, OLERENDER_NONE, NULL, NULL, pstg, (void**)&poo); CHECKNE(hr, S_OK, "OleCreateLink", errRet); hr = poo->SetMoniker(OLEWHICHMK_CONTAINER, pmkThis); CHECKNE(hr, S_OK, "SetMonikerOLEWHICHMK_CONTAINER", errRet); hr = poo->SetMoniker(OLEWHICHMK_OBJREL, pmkLink); CHECKNE(hr, S_OK, "SetMonikerOLEWHICHMK_OBJREL", errRet); hr = poo->QueryInterface(IID_IPersistStorage, (void**)&pps); CHECKNE(hr, S_OK, "QueryInterface(IID_IPersistStorage", errRet); hr = OleSave(pps, pstg, TRUE); CHECKNE(hr, S_OK, "OleSave", errRet); errRet: if (hr != S_OK) printf("CreateLink at %s line %d with hr=%08x\n", pszErr, iLine, hr); if (pbc) pbc->Release(); if (pmkSource) pmkSource->Release(); if (pstg) pstg->Release(); if (poo) poo->Release(); if (pmkThis) pmkThis->Release(); if (pmkLink) pmkLink->Release(); if (pps) pps->Release(); return hr; } HRESULT ResolveLink(WCHAR *pwszClient, WCHAR *pwszSource, BOOL fReSave) { HRESULT hr; IStorage *pstg = NULL; IOleLink *pol = NULL; WCHAR *pwszSourceFound = NULL; IPersistStorage *pps = NULL; char *pszErr; int iLine; hr = StgOpenStorage(pwszClient, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &pstg); CHECKNE(hr, S_OK, "StgOpenStorage(pwszClient", errRet); hr = OleLoad(pstg, IID_IOleLink, NULL, (void**)&pol); CHECKNE(hr, S_OK, "OleLoad(pstg, IID_IOleLink", errRet); hr = pol->BindToSource(0, NULL); CHECKNE(hr, S_OK, "pol->BindToSource", errRet); hr = pol->GetSourceDisplayName(&pwszSourceFound); CHECKNE(hr, S_OK, "pol->GetSourceDisplayName", errRet); if (wcsicmp(pwszSourceFound, pwszSource) != 0) { printf("SourceFound=%ls, SourceExpected=%ls\n", pwszSourceFound, pwszSource); pszErr = "'path compare'"; hr = E_FAIL; goto errRet; } if (fReSave) { hr = pol->QueryInterface(IID_IPersistStorage, (void**)&pps); CHECKNE(hr, S_OK, "pol->QueryInterface(IID_IPersistStorage", errRet); hr = OleSave(pps, pstg, TRUE); CHECKNE(hr, S_OK, "OleSave(pps, pstg, TRUE)", errRet); } errRet: if (hr != S_OK) printf("ResolveLink at %s line %d with hr=%08x\n", pszErr, iLine, hr); CoTaskMemFree(pwszSourceFound); if (pol) pol->Release(); if (pstg) pstg->Release(); if (pps) pps->Release(); return hr; } int __cdecl main(int argc, char **argv) { char * pszExit = "TEST FAILED."; int iExit = 1; WCHAR *pwszClient = NULL; WCHAR *pwszSource = NULL; HRESULT hr=E_FAIL; BOOL fArgsOk = FALSE; HRESULT hrExpected=S_OK; CoInitialize(NULL); OleInitialize(NULL); if (argc >= 3) { pwszClient = Convert(argv[2]); } if (argc >= 5) { pwszSource = Convert(argv[3]); sscanf(argv[4], "%x", &hrExpected); if (!pwszClient || !pwszSource) { pszExit = "Out of memory."; goto errExit; } } if (argc == 3) { if (stricmp(argv[1], "/t") == 0 || stricmp(argv[1], "-t") == 0) { // touch file creation date hr = TouchFile(pwszClient); fArgsOk = TRUE; } } else if (argc == 5) { if (stricmp(argv[1], "/c") == 0 || stricmp(argv[1], "-c") == 0) { // create link hr = CreateLink(pwszClient, pwszSource); fArgsOk = TRUE; } } else if (argc == 6) { if (stricmp(argv[1], "/r") == 0 || stricmp(argv[1], "-r") == 0) { // resolve link hr = ResolveLink(pwszClient, pwszSource, argv[5][0] == 's'); fArgsOk = TRUE; } } if (!fArgsOk) { pszExit = "Usage: /c client source expected_status -- create .lts file linked to source\n" " /r client expected_source expected_status save/nosave -- resolve .lts file, checked linked to source\n" " expected_source is ignored(but required) if not found during resolve.\n" " /t source -- change the creation date\n"; } else { if (hrExpected != hr) { printf("Expected status = %08X, actual status = %08X\n", hrExpected, hr); } else { pszExit = "TEST PASSED."; iExit = 0; } } errExit: OleUninitialize(); CoUninitialize(); delete pwszClient; delete pwszSource; puts(pszExit); return iExit; }