#include #pragma hdrstop #include #include "trkwks.hxx" #include "dltadmin.hxx" #include #include #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 \n"); printf( " ResolveLink -r \n"); printf( " where 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 ); }