217 lines
5.5 KiB
C++
217 lines
5.5 KiB
C++
|
#include <windows.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
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;
|
||
|
}
|