409 lines
12 KiB
C++
409 lines
12 KiB
C++
|
|
||
|
|
||
|
#include <pch.cxx>
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <ole2.h>
|
||
|
#include "trkwks.hxx"
|
||
|
#include "dltadmin.hxx"
|
||
|
#include <shlobj.h>
|
||
|
#include <shlguid.h>
|
||
|
|
||
|
#define CB_LINK_CLIENT_MAX 512
|
||
|
|
||
|
|
||
|
void
|
||
|
DoCreateLink(IShellLink * pshlink, const TCHAR *ptszLink, const TCHAR *ptszSrc)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
IPersistFile *pPersistFile = NULL;
|
||
|
|
||
|
DWORD dwWritten;
|
||
|
BYTE rgb[ CB_LINK_CLIENT_MAX ];
|
||
|
ULONG cbPersist = 0;
|
||
|
|
||
|
memset( rgb, 0, sizeof(rgb) );
|
||
|
|
||
|
hr = pshlink->QueryInterface( IID_IPersistFile, (void**) &pPersistFile );
|
||
|
if( FAILED(hr) )
|
||
|
{
|
||
|
_tprintf( TEXT("Couldn't QI IShellLink for IPersistFile (%08x)"), hr );
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
hr = pshlink->SetPath( ptszSrc );
|
||
|
_tprintf( TEXT("IShellLink::SetPath returned %08X\n"), hr );
|
||
|
if( S_OK != hr )
|
||
|
goto Exit;
|
||
|
|
||
|
hr = pPersistFile->Save( ptszLink, TRUE );
|
||
|
if( FAILED(hr) )
|
||
|
{
|
||
|
_tprintf( TEXT("Couldn't persist IShellLink (%08x"), hr );
|
||
|
goto Exit;
|
||
|
}
|
||
|
pPersistFile->SaveCompleted( ptszLink );
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
RELEASE_INTERFACE( pPersistFile );
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
TCHAR *
|
||
|
GetRestrict(DWORD r)
|
||
|
{
|
||
|
static TCHAR tszError[256];
|
||
|
|
||
|
tszError[0] = 0;
|
||
|
if (r == TRK_MEND_DEFAULT)
|
||
|
{
|
||
|
_tcscpy(tszError, TEXT("TRK_MEND_DEFAULT "));
|
||
|
}
|
||
|
if (r & TRK_MEND_DONT_USE_LOG)
|
||
|
{
|
||
|
_tcscat(tszError, TEXT("TRK_MEND_DONT_USE_LOG "));
|
||
|
}
|
||
|
if (r & TRK_MEND_DONT_USE_DC)
|
||
|
{
|
||
|
_tcscat(tszError, TEXT("TRK_MEND_DONT_USE_DC "));
|
||
|
}
|
||
|
if (r & TRK_MEND_SLEEP_DURING_MEND)
|
||
|
{
|
||
|
_tcscat(tszError, TEXT("TRK_MEND_SLEEP_DURING_SEARCH "));
|
||
|
}
|
||
|
if (r & TRK_MEND_DONT_SEARCH_ALL_VOLUMES)
|
||
|
{
|
||
|
_tcscat(tszError, TEXT("TRK_MEND_DONT_SEARCH_ALL_VOLUMES "));
|
||
|
}
|
||
|
if (r & TRK_MEND_DONT_USE_VOLIDS)
|
||
|
{
|
||
|
_tcscat(tszError, TEXT("TRK_MEND_DONT_USE_VOLIDS "));
|
||
|
}
|
||
|
return(tszError);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
enum EXTRAFLAGS
|
||
|
{
|
||
|
EXTRAFLAG_SHOW_IDS = 1
|
||
|
};
|
||
|
|
||
|
extern "C"
|
||
|
IID IID_ISLTracker
|
||
|
= { /* 7c9e512f-41d7-11d1-8e2e-00c04fb9386d */
|
||
|
0x7c9e512f,
|
||
|
0x41d7,
|
||
|
0x11d1,
|
||
|
{0x8e, 0x2e, 0x00, 0xc0, 0x4f, 0xb9, 0x38, 0x6d}
|
||
|
};
|
||
|
|
||
|
class ISLTracker : public IUnknown
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
STDMETHOD(QueryInterface) (REFIID riid, LPVOID * ppvObj) PURE;
|
||
|
STDMETHOD_(ULONG,AddRef) () PURE;
|
||
|
STDMETHOD_(ULONG,Release) () PURE;
|
||
|
|
||
|
STDMETHOD(Resolve)(HWND hwnd, DWORD fFlags, DWORD TrackerRestrictions) PURE;
|
||
|
STDMETHOD(GetIDs)(CDomainRelativeObjId *pdroidBirth, CDomainRelativeObjId *pdroidLast, CMachineId *pmcid) PURE;
|
||
|
}; // interface ISLTracker
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
DisplayIDs( ISLTracker *ptracker )
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
CDomainRelativeObjId droidBirth, droidLast;
|
||
|
CMachineId mcid;
|
||
|
TCHAR tsz[ MAX_PATH ];
|
||
|
TCHAR *ptsz = tsz;
|
||
|
|
||
|
hr = ptracker->GetIDs( &droidBirth, &droidLast, &mcid );
|
||
|
if( FAILED(hr) )
|
||
|
{
|
||
|
TrkLog(( TRKDBG_ERROR, TEXT("Couldn't get IDs") ));
|
||
|
TrkRaiseException( hr );
|
||
|
}
|
||
|
|
||
|
droidBirth.Stringize( tsz, sizeof(tsz) );
|
||
|
_tprintf( TEXT("Birth =\t%s\n"), tsz );
|
||
|
|
||
|
droidLast.Stringize( tsz, sizeof(tsz) );
|
||
|
_tprintf( TEXT("Last =\t%s\n"), tsz );
|
||
|
|
||
|
ptsz = tsz;
|
||
|
mcid.Stringize(ptsz);
|
||
|
_tprintf( TEXT("Machine =\t%s\n"), tsz );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
DoResolveLink(IShellLink * pshlink, const TCHAR * ptszLink, DWORD r, DWORD dwSLR, DWORD grfExtra,
|
||
|
DWORD dwTimeout )
|
||
|
{
|
||
|
IPersistFile * pPersistFile = NULL;
|
||
|
ISLTracker * ptracker = NULL;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
DWORD dwRead;
|
||
|
HRESULT hr;
|
||
|
WCHAR wszPath[MAX_PATH+1];
|
||
|
ULONG cbPath = sizeof(wszPath);
|
||
|
WIN32_FIND_DATA fd;
|
||
|
|
||
|
hr = pshlink->QueryInterface( IID_IPersistFile, (void**) &pPersistFile );
|
||
|
if( FAILED(hr) )
|
||
|
{
|
||
|
TrkLog((TRKDBG_ERROR, TEXT("Couldn't QI for IPersistFile")));
|
||
|
TrkRaiseException( hr );
|
||
|
}
|
||
|
|
||
|
hr = pPersistFile->Load( ptszLink, STGM_SHARE_EXCLUSIVE | STGM_READWRITE );
|
||
|
if( FAILED(hr) )
|
||
|
{
|
||
|
TrkLog((TRKDBG_ERROR, TEXT("Couldn't load IShellLink")));
|
||
|
TrkRaiseException( hr );
|
||
|
}
|
||
|
RELEASE_INTERFACE( pPersistFile );
|
||
|
|
||
|
if( (SLR_NO_UI & dwSLR) )
|
||
|
{
|
||
|
if( 0 != dwTimeout )
|
||
|
{
|
||
|
dwTimeout = min( dwTimeout, 0xfffe );
|
||
|
_tprintf( TEXT("Timeout = %d seconds\n"), dwTimeout/1000 );
|
||
|
}
|
||
|
}
|
||
|
else if( 0 != dwTimeout )
|
||
|
{
|
||
|
_tprintf( TEXT("Timeout will be ignored (since SLR_NO_UI isn't set)\n") );
|
||
|
}
|
||
|
|
||
|
// Track it
|
||
|
if( TRK_MEND_DEFAULT == r && 0 == grfExtra )
|
||
|
{
|
||
|
hr = pshlink->Resolve( (SLR_NO_UI & dwSLR) ? NULL : GetDesktopWindow(),
|
||
|
(dwTimeout<<16) | dwSLR | SLR_ANY_MATCH );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = pshlink->QueryInterface( IID_ISLTracker, (void**) &ptracker );
|
||
|
if( FAILED(hr) )
|
||
|
{
|
||
|
TrkLog((TRKDBG_ERROR, TEXT("Couldn't QI for ISLTracker")));
|
||
|
TrkRaiseException( hr );
|
||
|
}
|
||
|
|
||
|
if( EXTRAFLAG_SHOW_IDS & grfExtra )
|
||
|
DisplayIDs( ptracker );
|
||
|
|
||
|
hr = ptracker->Resolve( GetDesktopWindow(), (dwTimeout<<16) | dwSLR | SLR_ANY_MATCH, r );
|
||
|
|
||
|
if( EXTRAFLAG_SHOW_IDS & grfExtra )
|
||
|
DisplayIDs( ptracker );
|
||
|
}
|
||
|
|
||
|
pshlink->GetPath( wszPath, cbPath, &fd, 0 );
|
||
|
|
||
|
|
||
|
wprintf( L"%s %08X %s\n",
|
||
|
wszPath, hr, GetRestrict(r) );
|
||
|
|
||
|
RELEASE_INTERFACE( ptracker );
|
||
|
|
||
|
}
|
||
|
__except( BreakOnDebuggableException() )
|
||
|
{
|
||
|
RELEASE_INTERFACE( pPersistFile );
|
||
|
RELEASE_INTERFACE( ptracker );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
DltAdminLink( ULONG cArgs, TCHAR * const rgptszArgs[], ULONG *pcEaten )
|
||
|
{
|
||
|
BOOL fSuccess = FALSE;
|
||
|
HRESULT hr;
|
||
|
CMachineId mcid(MCID_LOCAL);
|
||
|
DWORD r = TRK_MEND_DEFAULT;
|
||
|
DWORD grfExtra = 0;
|
||
|
DWORD dwTimeout = 0;
|
||
|
DWORD dwSLR = 0; // SLR_ flags
|
||
|
IShellLink *pshlink = NULL;
|
||
|
WCHAR wszFullPath[ MAX_PATH + 1 ];
|
||
|
DWORD dwMoveFlags = MOVEFILE_FAIL_IF_NOT_TRACKABLE |
|
||
|
MOVEFILE_COPY_ALLOWED |
|
||
|
MOVEFILE_REPLACE_EXISTING;
|
||
|
|
||
|
|
||
|
*pcEaten = 0;
|
||
|
|
||
|
if( 0 == cArgs
|
||
|
||
|
||
|
rgptszArgs[0][0] != TEXT('-') && rgptszArgs[0][0] != TEXT('/') )
|
||
|
{
|
||
|
printf( "Invalid parameters. Use -? for usage info\n" );
|
||
|
*pcEaten = 0;
|
||
|
goto Exit;
|
||
|
}
|
||
|
else if( 1 <= cArgs && IsHelpArgument( rgptszArgs[0] ))
|
||
|
{
|
||
|
printf( "\nOption Link\n"
|
||
|
" Purpose: Create/resolve a shell link\n"
|
||
|
" Usage: -link [operation]\n"
|
||
|
" E.g.: -link -c LinkClient LinkSource\n"
|
||
|
" -link -r LinkClient\n"
|
||
|
" -link -rd LinkClient\n" );
|
||
|
|
||
|
printf( " Operations:\n" );
|
||
|
printf( " Operation Params\n");
|
||
|
printf( " --------- ------\n");
|
||
|
printf( " CreateLink -c <link> <src>\n");
|
||
|
printf( " ResolveLink -r<opts> <link>\n");
|
||
|
printf( " where <opts> may use:\n" );
|
||
|
printf( " -l = don't use log\n");
|
||
|
printf( " -d = don't use dc\n");
|
||
|
printf( " -i = don't use volids\n");
|
||
|
printf( " -m = don't scan all volumes on a machine\n");
|
||
|
printf( " -s = no search (SLR_NOSEARCH)\n");
|
||
|
printf( " -t = no track (SLR_NOTRACK)\n");
|
||
|
printf( " -x = show before/after droids\n");
|
||
|
printf( " -u = no UI (SLR_NOUI)\n");
|
||
|
printf( " -w(#)\n");
|
||
|
printf( " = Timeout (wait) seconds on IShellLink::Resolve\n");
|
||
|
printf( " -z = sleep in CTrkWksSvc::Mend\n");
|
||
|
|
||
|
*pcEaten = 1;
|
||
|
fSuccess = TRUE;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
hr = CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLink, (void**)&pshlink );
|
||
|
if( FAILED(hr) )
|
||
|
{
|
||
|
printf( "Couldn't get an IShellLink (%08x)\n", hr );
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
switch (rgptszArgs[0][1])
|
||
|
{
|
||
|
case TEXT('c'):
|
||
|
case TEXT('C'):
|
||
|
|
||
|
if( 3 <= cArgs )
|
||
|
{
|
||
|
*pcEaten = 3;
|
||
|
if( MAX_PATH < RtlGetFullPathName_U( rgptszArgs[2],
|
||
|
sizeof(wszFullPath),
|
||
|
wszFullPath, NULL ))
|
||
|
{
|
||
|
TrkLog(( TRKDBG_ERROR, TEXT("Couldn't get full path name") ));
|
||
|
goto Exit;
|
||
|
}
|
||
|
DoCreateLink( pshlink, rgptszArgs[1], wszFullPath );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TEXT('r'):
|
||
|
case TEXT('R'):
|
||
|
|
||
|
if( 2 <= cArgs )
|
||
|
{
|
||
|
*pcEaten = 2;
|
||
|
|
||
|
for( int i = 2; rgptszArgs[0][i] != TEXT('\0'); i++ )
|
||
|
{
|
||
|
switch(rgptszArgs[0][i])
|
||
|
{
|
||
|
case TEXT('l'):
|
||
|
case TEXT('L'):
|
||
|
r |= TRK_MEND_DONT_USE_LOG;
|
||
|
break;
|
||
|
case TEXT('d'):
|
||
|
case TEXT('D'):
|
||
|
r |= TRK_MEND_DONT_USE_DC;
|
||
|
break;
|
||
|
case TEXT('i'):
|
||
|
case TEXT('I'):
|
||
|
r |= TRK_MEND_DONT_USE_VOLIDS;
|
||
|
break;
|
||
|
case TEXT('m'):
|
||
|
case TEXT('M'):
|
||
|
r |= TRK_MEND_DONT_SEARCH_ALL_VOLUMES;
|
||
|
break;
|
||
|
case TEXT('s'):
|
||
|
case TEXT('S'):
|
||
|
dwSLR |= SLR_NOSEARCH;
|
||
|
break;
|
||
|
case TEXT('t'):
|
||
|
case TEXT('T'):
|
||
|
dwSLR |= SLR_NOTRACK;
|
||
|
break;
|
||
|
case TEXT('u'):
|
||
|
case TEXT('U'):
|
||
|
dwSLR |= SLR_NO_UI;
|
||
|
break;
|
||
|
case TEXT('x'):
|
||
|
case TEXT('X'):
|
||
|
grfExtra |= EXTRAFLAG_SHOW_IDS;
|
||
|
break;
|
||
|
case TEXT('z'):
|
||
|
case TEXT('Z'):
|
||
|
r |= TRK_MEND_SLEEP_DURING_MEND;
|
||
|
break;
|
||
|
|
||
|
case TEXT('w'):
|
||
|
case TEXT('W'):
|
||
|
|
||
|
// e.g. -link -rw(30)m
|
||
|
if( TEXT('(') == rgptszArgs[0][i+1] )
|
||
|
{
|
||
|
TCHAR *ptc = _tcschr( &rgptszArgs[0][i], TEXT(')') );
|
||
|
if( NULL != ptc )
|
||
|
{
|
||
|
if( 1 == _stscanf( &rgptszArgs[0][i+1], TEXT("(%d)"), &dwTimeout ))
|
||
|
{
|
||
|
dwTimeout *= 1000; // => milliseconds
|
||
|
i = ( (BYTE*) ptc - (BYTE*) rgptszArgs[0] ) / sizeof(TCHAR);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
default:
|
||
|
_tprintf( TEXT("Bad Resolve switch: %c\n"), rgptszArgs[0][i] );
|
||
|
goto Exit;
|
||
|
} // switch
|
||
|
} // for
|
||
|
|
||
|
DoResolveLink( pshlink, rgptszArgs[1], r, dwSLR, grfExtra, dwTimeout );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
_tprintf( TEXT("Invalid Link option: %c\n"), rgptszArgs[0][1] );
|
||
|
*pcEaten = 1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
RELEASE_INTERFACE( pshlink );
|
||
|
|
||
|
return( fSuccess );
|
||
|
}
|