windows-nt/Source/XPSP1/NT/com/svcdlls/trksvcs/dltadmin/link.cxx

409 lines
12 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
#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 );
}