typedef struct _TASK_ATTRIBUTE
{
LPTSTR m_pszAttribute;
int m_iIndex;
} TASK_ATTRIBUTE;
static TASK_ATTRIBUTE spTaskAttributes[] =
{
{ KEYWORD_JOB_ACCOUNT, INDEX_JOB_ACCOUNT },
{ KEYWORD_JOB_PASSWORD, INDEX_JOB_PASSWORD },
{ KEYWORD_JOB_COMMENT, INDEX_JOB_COMMENT },
{ KEYWORD_JOB_CREATOR, INDEX_JOB_CREATOR },
{ KEYWORD_JOB_RETRY_COUNT, INDEX_JOB_RETRY_COUNT },
{ KEYWORD_JOB_RETRY_INTERVAL, INDEX_JOB_RETRY_INTERVAL },
{ KEYWORD_JOB_IDLE_MINUTES, INDEX_JOB_IDLE_MINUTES },
{ KEYWORD_JOB_DEADLINE_MINUTES, INDEX_JOB_DEADLINE_MINUTES },
{ KEYWORD_JOB_DATA, INDEX_JOB_DATA },
{ KEYWORD_JOB_APPLICATION, INDEX_JOB_APPLICATION },
{ KEYWORD_JOB_EXIT_CODE, INDEX_JOB_EXIT_CODE },
{ KEYWORD_JOB_MAX_RUN_TIME, INDEX_JOB_MAX_RUN_TIME },
{ KEYWORD_JOB_FLAGS, INDEX_JOB_FLAGS },
{ KEYWORD_JOB_DIRECTORY, INDEX_JOB_DIRECTORY },
{ KEYWORD_JOB_PRIORITY, INDEX_JOB_PRIORITY },
{ KEYWORD_JOB_PARAMETERS, INDEX_JOB_PARAMETERS },
{ KEYWORD_JOB_LAST_RUN_TIME, INDEX_JOB_LAST_RUN_TIME },
{ KEYWORD_JOB_NEXT_RUN_TIME, INDEX_JOB_NEXT_RUN_TIME },
{ KEYWORD_JOB_RUN_TIMES, INDEX_JOB_RUN_TIMES },
{ NULL, INDEX_JOB_BAD_ATTRIBUTE }
};
// #define GET_TASK_INTERFACE(x) ExtractTaskInterface( PERL_OBJECT_ARGS (x) )
#define GET_TASK_INTERFACE(x) (ITask *) HASH_GET_IV( (x), KEYWORD_TASK_INTERFACE );
/*
inline ITask* ExtractTaskInterface( PERL_OBJECT_PROTO HV *pHvTiedHash )
{
MAGIC *pMagic = mg_find( (SV*) pHvTiedHash, 'P' );
HV *pHv = NULL;
ITask *pTask = NULL;
if( NULL != pMagic )
{
if( NULL != ( pHv = (HV*) pMagic->mg_obj ) )
{
pTask = (ITask *) HASH_GET_IV( pHv, KEYWORD_TASK_INTERFACE );
}
}
return( pTask );
}
*/
///////////////////////////////////////////////////////////////////////
//
DWORD GetAttributeIndex( LPCTSTR pszAttribute )
{
DWORD dwIndex = 0;
while( NULL != spTaskAttributes[ dwIndex ].m_pszAttribute )
{
if( 0 == _tcsicmp( spTaskAttributes[ dwIndex ].m_pszAttribute, pszAttribute ) )
{
return( dwIndex );
}
++dwIndex;
}
return( INDEX_JOB_BAD_ATTRIBUTE );
}
///////////////////////////////////////////////////////////////////////
//
HRESULT SaveTask( ITask *pTask )
{
IPersistFile *pPersistFile;
HRESULT hr = S_FALSE;
if( NULL != pTask )
{
if( SUCCEEDED( pTask->QueryInterface( IID_IPersistFile, (void **) &pPersistFile ) ) )
{
hr = pPersistFile->Save( NULL, TRUE );
// Release the IPersistFile interface.
pPersistFile->Release();
}
}
return( hr );
}
///////////////////////////////////////////////////////////////////////
//
DWORD SystemTimeToCTime( SYSTEMTIME *psTime )
{
time_t c_TimeValue = 0;
struct tm c_sTime;
ZeroMemory( &c_sTime, sizeof( c_sTime ) );
c_sTime.tm_sec = psTime->wSecond;
c_sTime.tm_min = psTime->wMinute;
c_sTime.tm_hour = psTime->wHour;
c_sTime.tm_mday = psTime->wDay;
c_sTime.tm_mon = psTime->wMonth - 1;
c_sTime.tm_year = psTime->wYear - 1900;
return( mktime( &c_sTime ) );
}
///////////////////////////////////////////////////////////////////////
//
HRESULT ModifyTask( PERL_OBJECT_PROTO ITask *pTask, HV *pHv )
{
CUString szuBuffer;
LPTSTR pszAttributeKeyName = NULL;
LPTSTR pszBuffer = NULL;
DWORD dwBuffer = 0;
DWORD dwKeyLen = 0;
WORD wBuffer = 0;
HRESULT hr = ERROR_SUCCESS;
enum { Unknown, String, Dword } eValueType = Unknown;
SV *pSv;
if( ( NULL == pTask ) || ( NULL == pHv ) )
{
return( S_FALSE );
}
hv_iterinit( pHv );
while( ( SUCCEEDED( hr ) && ( NULL != hv_iternextsv( pHv, &pszAttributeKeyName, (long*) &dwKeyLen ) ) ) )
{
switch( GetAttributeIndex( pszAttributeKeyName ) )
{
case INDEX_JOB_ACCOUNT:
if( SUCCEEDED( hr ) )
{
CUString szuBuffer2;
szuBuffer = HASH_GET_PV( pHv, KEYWORD_JOB_ACCOUNT );
szuBuffer2 = HASH_GET_PV( pHv, KEYWORD_JOB_PASSWORD );
hr = pTask->SetAccountInformation( szuBuffer, szuBuffer2 );
}
break;
case INDEX_JOB_PASSWORD:
if( ! HASH_KEY_EXISTS( pHv, KEYWORD_JOB_ACCOUNT ) )
{
LPWSTR pszwAccount;
hr = pTask->GetAccountInformation( &pszwAccount );
if( SUCCEEDED( hr ) )
{
szuBuffer = HASH_GET_PV( pHv, KEYWORD_JOB_PASSWORD );
hr = pTask->SetAccountInformation( pszwAccount, szuBuffer );
CoTaskMemFree( pszwAccount );
}
}
break;
case INDEX_JOB_COMMENT:
if( SUCCEEDED( hr ) )
{
szuBuffer = HASH_GET_PV( pHv, KEYWORD_JOB_COMMENT );
hr = pTask->SetComment( szuBuffer );
}
break;
case INDEX_JOB_CREATOR:
if( SUCCEEDED( hr ) )
{
szuBuffer = HASH_GET_PV( pHv, KEYWORD_JOB_CREATOR );
hr = pTask->SetCreator( szuBuffer );
}
break;
/*
// WinNT/2000 does not currently implement this method (as per the SDK).
case INDEX_JOB_RETRY_COUNT:
if( SUCCEEDED( hr ) )
{
dwBuffer = HASH_GET_IV( pHv, KEYWORD_JOB_RETRY_COUNT );
hr = pTask->SetErrorRetryCount( dwBuffer );
}
break;
*/
/*
// WinNT/2000 does not currently implement this method (as per the SDK).
case INDEX_JOB_RETRY_INTERVAL:
if( SUCCEEDED( hr ) )
{
dwBuffer = HASH_GET_IV( pHv, KEYWORD_JOB_RETRY_INTERVAL );
pTask->SetErrorRetryInterval( dwBuffer );
}
break;
*/
case INDEX_JOB_IDLE_MINUTES:
if( SUCCEEDED( hr ) )
{
DWORD dwBuffer2;
dwBuffer = HASH_GET_IV( pHv, KEYWORD_JOB_IDLE_MINUTES );
dwBuffer2 = HASH_GET_IV( pHv, KEYWORD_JOB_DEADLINE_MINUTES );
hr = pTask->SetIdleWait( dwBuffer, dwBuffer2 );
}
break;
case INDEX_JOB_DEADLINE_MINUTES:
if( SUCCEEDED( hr ) )
{
DWORD dwBuffer2;
dwBuffer = HASH_GET_IV( pHv, KEYWORD_JOB_IDLE_MINUTES );
dwBuffer2 = HASH_GET_IV( pHv, KEYWORD_JOB_DEADLINE_MINUTES );
hr = pTask->SetIdleWait( dwBuffer, dwBuffer2 );
}
break;
case INDEX_JOB_DATA:
break;
// Read only value
case INDEX_JOB_LAST_RUN_TIME:
break;
// Read only value
case INDEX_JOB_NEXT_RUN_TIME:
break;
// Read only value
case INDEX_JOB_RUN_TIMES:
break;
case INDEX_JOB_APPLICATION:
if( SUCCEEDED( hr ) )
{
szuBuffer = HASH_GET_PV( pHv, KEYWORD_JOB_APPLICATION );
hr = pTask->SetApplicationName( szuBuffer );
}
break;
case INDEX_JOB_EXIT_CODE:
break;
case INDEX_JOB_MAX_RUN_TIME:
if( SUCCEEDED( hr ) )
{
dwBuffer = HASH_GET_IV( pHv, KEYWORD_JOB_MAX_RUN_TIME );
pTask->SetMaxRunTime( dwBuffer );
}
break;
case INDEX_JOB_FLAGS:
if( SUCCEEDED( hr ) )
{
dwBuffer = HASH_GET_IV( pHv, KEYWORD_JOB_FLAGS );
pTask->SetFlags( dwBuffer );
}
break;
case INDEX_JOB_DIRECTORY:
if( SUCCEEDED( hr ) )
{
szuBuffer = HASH_GET_PV( pHv, KEYWORD_JOB_DIRECTORY );
hr = pTask->SetWorkingDirectory( szuBuffer );
}
break;
case INDEX_JOB_PRIORITY:
if( SUCCEEDED( hr ) )
{
dwBuffer = HASH_GET_IV( pHv, KEYWORD_JOB_PRIORITY );
pTask->SetPriority( dwBuffer );
}
break;
case INDEX_JOB_PARAMETERS:
if( SUCCEEDED( hr ) )
{
szuBuffer = HASH_GET_PV( pHv, KEYWORD_JOB_PARAMETERS );
hr = pTask->SetParameters( szuBuffer );
}
break;
case INDEX_JOB_BAD_ATTRIBUTE:
default:
// OOohh bad!
break;
}
}
return( hr );
}
///////////////////////////////////////////////////////////////////////
//
XS(XS_Win32__Scheduler_Task_TIE_FETCH)
{
dXSARGS;
EXTENSION_VARS;
HV *pHvSelf;
ITask *pTask = NULL;
HRESULT hr = ERROR_SUCCESS;
DWORD dwTotal = 0;
BOOL fResult = FALSE;
LPTSTR pszName = NULL;
SV *pSvResult = NULL;
if (items != 2)
{
croak("Usage: " EXTENSION "::Task::TIEFETCH( $Self, $Key )\n");
}
// FETCH
pHvSelf = (HV*) SvRV( ST( 0 ) );
pszName = SvPV( ST( 1 ), na );
pTask = GET_TASK_INTERFACE( pHvSelf );
if( NULL != pTask )
{
CUString szuBuffer( pszName );
LPTSTR pszAttributeKeyName = NULL;
LPTSTR pszBuffer = NULL;
LPWSTR pszwBuffer = NULL;
DWORD dwBuffer = 0;
WORD wBuffer = 0;
AV *pAv = NULL;
enum { Unknown, String, Dword, Array } eValueType = Unknown;
switch( GetAttributeIndex( pszName ) )
{
case INDEX_JOB_ACCOUNT:
if( SUCCEEDED( pTask->GetAccountInformation( &pszwBuffer ) ) )
{
szuBuffer = pszwBuffer;
pszAttributeKeyName = KEYWORD_JOB_ACCOUNT;
CoTaskMemFree ( pszBuffer );
eValueType = String;
}
break;
case INDEX_JOB_PASSWORD:
break;
case INDEX_JOB_LAST_RUN_TIME:
{
SYSTEMTIME sTime;
ZeroMemory( &sTime, sizeof( sTime ) );
if( SUCCEEDED( pTask->GetMostRecentRunTime( &sTime ) ) )
{
dwBuffer = SystemTimeToCTime( &sTime );
pszAttributeKeyName = KEYWORD_JOB_LAST_RUN_TIME;
eValueType = Dword;
}
}
break;
case INDEX_JOB_RUN_TIMES:
{
SYSTEMTIME sTime;
SYSTEMTIME *psTime = NULL;
WORD wCount = TOTAL_RUN_TIME_TO_FETCH;
ZeroMemory( &sTime, sizeof( sTime ) );
GetSystemTime( &sTime );
if( SUCCEEDED( pTask->GetRunTimes( &sTime, NULL, &wCount, (SYSTEMTIME **) &psTime ) ) )
{
pAv = newAV();
if( NULL != pAv )
{
DWORD dwIndex = 0;
while( dwIndex < wCount )
{
dwBuffer = SystemTimeToCTime( &psTime[ dwIndex++ ] );
ARRAY_PUSH_IV( pAv, dwBuffer );
}
pszAttributeKeyName = KEYWORD_JOB_LAST_RUN_TIME;
eValueType = Array;
}
CoTaskMemFree( psTime );
}
}
break;
case INDEX_JOB_NEXT_RUN_TIME:
{
SYSTEMTIME sTime;
ZeroMemory( &sTime, sizeof( sTime ) );
if( SUCCEEDED( pTask->GetNextRunTime( &sTime ) ) )
{
dwBuffer = SystemTimeToCTime( &sTime );
pszAttributeKeyName = KEYWORD_JOB_NEXT_RUN_TIME;
eValueType = Dword;
}
}
break;
case INDEX_JOB_COMMENT:
if( SUCCEEDED( pTask->GetComment( &pszwBuffer ) ) )
{
szuBuffer = pszwBuffer;
pszAttributeKeyName = KEYWORD_JOB_COMMENT;
CoTaskMemFree ( pszBuffer );
eValueType = String;
}
break;
case INDEX_JOB_CREATOR:
if( SUCCEEDED( pTask->GetCreator( &pszwBuffer ) ) )
{
szuBuffer = pszwBuffer;
pszAttributeKeyName = KEYWORD_JOB_CREATOR;
CoTaskMemFree ( pszBuffer );
eValueType = String;
}
break;
/*
// WinNT/2000 does not currently implement this method (as per the SDK).
case INDEX_JOB_RETRY_COUNT:
if( SUCCEEDED( pTask->GetErrorRetryCount( &wBuffer ) ) )
{
pszAttributeKeyName = KEYWORD_JOB_RETRY_COUNT;
dwBuffer = wBuffer;
eValueType = Dword;
}
break;
*/
/*
// WinNT/2000 does not currently implement this method (as per the SDK).
case INDEX_JOB_RETRY_INTERVAL:
if( SUCCEEDED( pTask->GetErrorRetryInterval( &wBuffer ) ) )
{
pszAttributeKeyName = KEYWORD_JOB_RETRY_INTERVAL;
dwBuffer = wBuffer;
eValueType = Dword;
}
break;
*/
case INDEX_JOB_IDLE_MINUTES:
{
WORD wBuffer2;
if( SUCCEEDED( pTask->GetIdleWait( &wBuffer, &wBuffer2 ) ) )
{
pszAttributeKeyName = KEYWORD_JOB_IDLE_MINUTES;
dwBuffer = wBuffer;
eValueType = Dword;
}
}
break;
case INDEX_JOB_DEADLINE_MINUTES:
{
WORD wBuffer2;
if( SUCCEEDED( pTask->GetIdleWait( &wBuffer, &wBuffer2 ) ) )
{
pszAttributeKeyName = KEYWORD_JOB_DEADLINE_MINUTES;
dwBuffer = wBuffer2;
eValueType = Dword;
}
}
break;
case INDEX_JOB_DATA:
break;
case INDEX_JOB_APPLICATION:
if( SUCCEEDED( pTask->GetApplicationName( &pszwBuffer ) ) )
{
szuBuffer = pszwBuffer;
pszAttributeKeyName = KEYWORD_JOB_APPLICATION;
CoTaskMemFree ( pszBuffer );
eValueType = String;
}
break;
case INDEX_JOB_EXIT_CODE:
if( SUCCEEDED( pTask->GetExitCode( &dwBuffer ) ) )
{
pszAttributeKeyName = KEYWORD_JOB_EXIT_CODE;
eValueType = Dword;
}
break;
case INDEX_JOB_MAX_RUN_TIME:
if( SUCCEEDED( pTask->GetMaxRunTime( &dwBuffer ) ) )
{
pszAttributeKeyName = KEYWORD_JOB_MAX_RUN_TIME;
eValueType = Dword;
}
break;
case INDEX_JOB_FLAGS:
if( SUCCEEDED( pTask->GetFlags( &dwBuffer ) ) )
{
pszAttributeKeyName = KEYWORD_JOB_FLAGS;
eValueType = Dword;
}
break;
case INDEX_JOB_DIRECTORY:
if( SUCCEEDED( pTask->GetWorkingDirectory( &pszwBuffer ) ) )
{
szuBuffer = pszwBuffer;
pszAttributeKeyName = KEYWORD_JOB_DIRECTORY;
CoTaskMemFree ( pszBuffer );
eValueType = String;
}
break;
case INDEX_JOB_PRIORITY:
if( SUCCEEDED( pTask->GetPriority( &dwBuffer ) ) )
{
pszAttributeKeyName = KEYWORD_JOB_PRIORITY;
eValueType = Dword;
}
break;
case INDEX_JOB_PARAMETERS:
if( SUCCEEDED( pTask->GetParameters( &pszwBuffer ) ) )
{
szuBuffer = pszwBuffer;
pszAttributeKeyName = KEYWORD_JOB_PARAMETERS;
CoTaskMemFree ( pszBuffer );
eValueType = String;
}
break;
case INDEX_JOB_BAD_ATTRIBUTE:
default:
// OOohh bad!
break;
}
/*
if( NULL != pHv )
{
switch( eValueType )
{
case String:
HASH_STORE_PV( pHv, pszAttributeKeyName, (LPTSTR) pszuBuffer );
break;
case Dword:
HASH_STORE_IV( pHv, pszAttributeKeyName, (DWORD) dwBuffer );
dwBuffer = 0;
break;
case Array:
HASH_STORE_AV( pHv, pszAttributeKeyName, pAv );
pAv = NULL;
break;
}
}
else
*/
{
switch( eValueType )
{
case String:
PUSH_PV( (LPTSTR) szuBuffer );
break;
case Dword:
PUSH_IV( dwBuffer );
break;
case Array:
PUSH_AV( pAv );
break;
}
}
}
EXTENSION_RETURN;
}
///////////////////////////////////////////////////////////////////////
//
XS( XS_Win32__Scheduler_Task_TIE_STORE )
{
dXSARGS;
EXTENSION_VARS;
HV *pHv = NULL;
HV *pHvSelf;
ITask *pTask = NULL;
HRESULT hr = ERROR_SUCCESS;
DWORD dwTotal = 0;
BOOL fResult = FALSE;
LPTSTR pszName = NULL;
SV *pSvResult = NULL;
if (items != 2)
{
croak("Usage: " EXTENSION "::Task::TIESTORE( $Self, $Key, [ $Value | \\%Hash ] )\n");
}
// FETCH
pHvSelf = (HV*) SvRV( ST( 0 ) );
if( NULL == ( pHv = EXTRACT_HV( ST( 2 ) ) ) )
{
// If a hash reference was not passed in then let's
// create a temporary one so that later it is easier to
// iterate through the hash keys. Otherwise we will have
// to have code for a hash and other code for scalar.
if( NULL != ( pHv = newHV() ) )
{
HASH_STORE_SVNOREF( pHv, SvPV( ST( 1 ), na ), ST( 2 ) );
}
}
// NOTE: If we passed in a hash reference then the key is
// ignored. We will use the keys and values from the
// hash.
pTask = GET_TASK_INTERFACE( pHvSelf );
if( NULL != pTask )
{
HRESULT hr = ModifyTask( PERL_OBJECT_ARGS pTask, pHv );
if( SUCCEEDED( hr ) )
{
if( SUCCEEDED( SaveTask( pTask ) ) )
{
PUSH_IV( 1 );
}
}
}
EXTENSION_RETURN;
}
///////////////////////////////////////////////////////////////////////
//
XS(XS_Win32__Scheduler_Task_TIE_FIRSTKEY)
{
dXSARGS;
EXTENSION_VARS;
HV *pHvSelf;
ITask *pTask = NULL;
if( 1 != items )
{
croak( "Usage: " EXTENSION "::Task::FIRSTKEY( $Self )\n" );
}
pHvSelf = (HV*) SvRV( ST( 0 ) );
pTask = GET_TASK_INTERFACE( pHvSelf );
if( NULL != pTask )
{
PUSH_PV( spTaskAttributes[ 0 ].m_pszAttribute );
}
EXTENSION_RETURN;
}
///////////////////////////////////////////////////////////////////////
//
XS(XS_Win32__Scheduler_Task_TIE_NEXTKEY)
{
dXSARGS;
EXTENSION_VARS;
HV *pHvSelf;
ITask *pTask = NULL;
LPTSTR pszPreviousKey = NULL;
if( 2 != items )
{
croak( "Usage: " EXTENSION "::Task::NEXTKEY( $Self, $PreviousKey )\n" );
}
pszPreviousKey = SvPV( ST( 1 ), na );
pHvSelf = (HV*) SvRV( ST( 0 ) );
pTask = GET_TASK_INTERFACE( pHvSelf );
if( NULL != pTask )
{
DWORD dwIndex = GetAttributeIndex( pszPreviousKey );
if( ( INDEX_JOB_BAD_ATTRIBUTE != dwIndex++ )
&& ( NULL != spTaskAttributes[ dwIndex ].m_pszAttribute ) )
{
PUSH_PV( spTaskAttributes[ dwIndex ].m_pszAttribute );
}
}
EXTENSION_RETURN;
}
///////////////////////////////////////////////////////////////////////
//
XS(XS_Win32__Scheduler_Task_TIE_EXISTS)
{
dXSARGS;
EXTENSION_VARS;
HV *pHvSelf;
ITask *pTask = NULL;
HRESULT hr = ERROR_SUCCESS;
LPTSTR pszKey = NULL;
DWORD dwTotal = 0;
BOOL fResult = FALSE;
if( 2 != items )
{
croak( "Usage: " EXTENSION "::Task::EXISTS( $Self, $Key )\n" );
}
pszKey = SvPV( ST( 1 ), na);
pHvSelf = (HV*) SvRV( ST( 0 ) );
pTask = GET_TASK_INTERFACE( pHvSelf );
if( NULL != pTask )
{
if( INDEX_JOB_BAD_ATTRIBUTE != GetAttributeIndex( pszKey ) )
{
fResult = TRUE;
}
}
EXTENSION_RETURN_BOOL( fResult );
}
///////////////////////////////////////////////////////////////////////
//
XS(XS_Win32__Scheduler_Task_TIE_DELETE)
{
dXSARGS;
EXTENSION_VARS;
HV *pHvSelf;
ITask *pTask = NULL;
HRESULT hr = S_FALSE;
CUString szuName;
if( 2 != items )
{
croak( "Usage: " EXTENSION "::Task::DELETE( $Self, $Key )\n" );
}
// DELETE
pHvSelf = (HV*) SvRV( ST( 0 ) );
szuName = SvPV( ST( 1 ), na);
pTask = GET_TASK_INTERFACE( pHvSelf );
if( NULL != pTask )
{
//hr = pTask->Delete( szuName );
// Here we must set the szuName attribute to 0 or ""
}
EXTENSION_RETURN_BOOL( SUCCEEDED( hr ) );
}
///////////////////////////////////////////////////////////////////////
//
XS(XS_Win32__Scheduler_Task_TIE_DESTROY)
{
dXSARGS;
EXTENSION_VARS;
HV *pHvSelf;
ITask *pTask = NULL;
if( 1 != items )
{
croak( "Usage: " EXTENSION "::Task::DESTROY( $Self )\n" );
}
// DESTROY
pHvSelf = (HV*) SvRV( ST( 0 ) );
pTask = GET_TASK_INTERFACE( pHvSelf );
if( NULL != pTask )
{
pTask->Release();
HASH_STORE_IV( pHvSelf, KEYWORD_TASK_INTERFACE, 0 );
}
XSRETURN_EMPTY;
}