|
|
//____________________________________________________________________________
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995 - 1996.
//
// File: job.cxx
//
// Contents:
//
// Classes: None.
//
// Functions:
//
// History: 14-Mar-96 EricB created
// 21-Jun-96 MarkBl Renamed from jobedit.cxx since now Save() &
// Get/SetAccountInformation members require
// client-side rpc. Their implementations must
// reside here so we don't have to include the
// client-side RPC in the service. Also added
// Get/SetAccountInformation members.
//
// Notes: Disabled security code completely for Win95. This will be
// enabled in the next release of the scheduling agent.
//
// BUGBUG : The classes should be split into a core base class,
// then have an OLE-supporting class inherit from it.
// The core class would exist in the service. The sub-
// class in the dll.
//
//____________________________________________________________________________
#include "..\pch\headers.hxx"
#pragma hdrstop
#if !defined(_CHICAGO_)
#include "network.hxx"
#endif // !defined(_CHICAGO_)
#include "misc.hxx"
#include "job_cls.hxx"
#include "debug.hxx"
#if !defined(_CHICAGO_)
#include "defines.hxx"
#endif // !defined(_CHICAGO_)
#if !defined(_CHICAGO_)
#include "SASecRPC.h" // Get/SetAccountInformation RPC definition.
#endif // !defined(_CHICAGO_)
#if !defined(_CHICAGO_)
typedef DWORD (WINAPI * PWNETGETUNIVERSALNAMEW)(LPCWSTR, DWORD, LPVOID, LPDWORD);
PWNETGETUNIVERSALNAMEW gpWNetGetUniversalNameW = NULL; #endif // !defined(_CHICAGO_)
HRESULT DisplayJobProperties(LPTSTR, ITask *); //
// This operation is not supported locally on Win95, and for the first
// release of the scheduling agent, neither remotely from Win95 to NT.
//
#if !defined(_CHICAGO_)
void ResetAccountInfo(PJOB_ACCOUNT_INFO pAccountInfo); #endif // !defined(_CHICAGO_)
//+----------------------------------------------------------------------------
//
// Member: CJob::ITask::EditWorkItem
//
// Synopsis: Invoke the edit job property sheet.
//
//-----------------------------------------------------------------------------
STDMETHODIMP CJob::EditWorkItem(HWND hParent, DWORD dwReserved) { if (m_ptszFileName != NULL && m_ptszFileName[0] != TEXT('\0')) { return DisplayJobProperties(m_ptszFileName, (ITask *)this); }
return STG_E_NOTFILEBASEDSTORAGE; }
//+----------------------------------------------------------------------------
//
// CJob::IProvideTaskPage::GetPage method
//
//-----------------------------------------------------------------------------
STDMETHODIMP I_GetTaskPage( ITask * pITask, TASKPAGE tpType, BOOL fPersistChanges, HPROPSHEETPAGE * phPage);
STDMETHODIMP CJob::GetPage( TASKPAGE tpType, BOOL fPersistChanges, HPROPSHEETPAGE * phPage) { return I_GetTaskPage((ITask *)this, tpType, fPersistChanges, phPage); }
//+----------------------------------------------------------------------------
//
// Member: CJob::ITask::SetAccountInformation
//
// Synopsis: Set the name and password of the account to be used for running
// this job.
//
// Arguments: [pwszAccountName] -- Account name.
// [pwszPassword] -- Account password.
//
// Returns: S_OK
// E_INVALIDARG
// E_OUTOFMEMORY
//
// Notes: Both strings are caller allocated and freed.
//
//-----------------------------------------------------------------------------
STDMETHODIMP CJob::SetAccountInformation(LPCWSTR pwszAccountName, LPCWSTR pwszPassword) { TRACE(CJob, SetAccountInformation)
if( NULL == pwszAccountName ) { return E_INVALIDARG; } //
// This operation is not supported locally on Win95, and for the first
// release of the scheduling agent, neither remotely from Win95 to NT.
//
#if !defined(_CHICAGO_)
HRESULT hr;
//
// Need to allocate the private data member structure containing copies
// of the account arguments.
//
// Note, could allocate everything within a single buffer, but since
// this operation is performed so rarely, it really isn't worth it.
//
PJOB_ACCOUNT_INFO pAccountInfo = new JOB_ACCOUNT_INFO;
if (pAccountInfo == NULL) { return(E_OUTOFMEMORY); }
pAccountInfo->pwszPassword = NULL; pAccountInfo->pwszAccount = new WCHAR[wcslen(pwszAccountName) + 1];
if (pAccountInfo->pwszAccount != NULL) { wcscpy(pAccountInfo->pwszAccount, pwszAccountName); } else { hr = E_OUTOFMEMORY; goto ErrorExit; }
if (pwszPassword != NULL) { pAccountInfo->pwszPassword = new WCHAR[wcslen(pwszPassword) + 1];
if (pAccountInfo->pwszPassword != NULL) { wcscpy(pAccountInfo->pwszPassword, pwszPassword); } else { hr = E_OUTOFMEMORY; goto ErrorExit; } }
if (m_pAccountInfo != NULL) { ResetAccountInfo(m_pAccountInfo); delete m_pAccountInfo; } m_pAccountInfo = pAccountInfo;
//
// Setting this flag will result in the RPC call to set the account
// information on object save (IPersistFile::Save()).
//
this->SetFlag(JOB_I_FLAG_SET_ACCOUNT_INFO);
return(S_OK);
ErrorExit: if (pAccountInfo != NULL) { ResetAccountInfo(pAccountInfo); delete pAccountInfo; }
return(hr); #else
return(SCHED_E_NO_SECURITY_SERVICES);
#endif // !defined(_CHICAGO)
}
//+----------------------------------------------------------------------------
//
// Member: CJob::ITask::GetAccountInformation
//
// Synopsis: Get the name of the account to be used for this job.
//
// Arguments: [ppwszAccountName] - the returned string buffer
//
// Returns: HRESULTS
//
// Notes: The string is callee allocated and caller freed with
// CoTaskMemFree.
//
//-----------------------------------------------------------------------------
STDMETHODIMP CJob::GetAccountInformation(LPWSTR * ppwszAccountName) { TRACE3(CJob, GetAccountInformation)
//
// This operation is not supported locally on Win95, and for the first
// release of the scheduling agent, neither remotely from Win95 to NT.
//
#if !defined(_CHICAGO_)
HRESULT hr;
//
// Unexpected, but possible should the caller CoCreateInstance a new
// job, then call this member w/o IPersistFile::Load/Save.
//
if (m_ptszFileName == NULL) { schDebugOut((DEB_ERROR, "GetAccountInformation called with no filename\n")); return(E_UNEXPECTED); }
//
// Return cached account name. If it hasn't been obtained, we'll
// need to RPC to the server to get it.
//
WCHAR wszAccountName[MAX_USERNAME + 1]; WCHAR * pwszAccountName = NULL;
if (m_pAccountInfo == NULL) { //
// RPC to the server local to this job to fetch the account name
// associated with this job.
//
// First, figure out if this is a remote job. If so, fetch the server
// name on which the job resides.
//
WCHAR wszFileName[MAX_PATH + 1] = L""; WCHAR wszUNCPath[MAX_PATH + 1]; WCHAR * pwszFileName; WCHAR * pwszServerName;
#if !defined(UNICODE)
HRESULT hr = AnsiToUnicode(wszFileName, m_ptszFileName, MAX_PATH+1);
if (FAILED(hr)) { return E_INVALIDARG; } pwszFileName = wszFileName; #else
pwszFileName = m_ptszFileName; #endif // UNICODE
//
// Fetch the server name associated with the network path. If the path
// is local, the server name returned will be NULL.
//
hr = GetServerNameFromPath(pwszFileName, (MAX_PATH + 1) * sizeof(WCHAR), wszUNCPath, &pwszServerName);
if (FAILED(hr)) { return(hr); }
#if defined(_CHICAGO_)
//
// Local security operations are not supported on Win95.
//
if (pwszServerName == NULL) { return(SCHED_E_NO_SECURITY_SERVICES); } #endif // _CHICAGO_
//
// RPC to the service to fetch the account name.
//
// First, isolate the relative job name from the remaining path.
//
WCHAR * pwszRelativeFileName;
if (pwszFileName != NULL) { pwszRelativeFileName = wcsrchr(pwszFileName, L'\\');
if (pwszRelativeFileName != NULL) { pwszRelativeFileName++; } else { pwszRelativeFileName = pwszFileName; } }
DWORD ccAccountName = MAX_USERNAME;
RpcTryExcept { hr = SAGetAccountInformation(pwszServerName, pwszRelativeFileName, ccAccountName, wszAccountName); } RpcExcept(1) { DWORD Status = RpcExceptionCode(); schDebugOut((DEB_ERROR, "GetAccountInformation exception(0x%x)\n", Status)); hr = SchedMapRpcError(Status); } RpcEndExcept;
if (SUCCEEDED(hr)) { pwszAccountName = wszAccountName; } } else { schAssert(m_pAccountInfo->pwszAccount != NULL); pwszAccountName = m_pAccountInfo->pwszAccount; hr = S_OK; }
//
// Allocate returned name.
//
if (pwszAccountName != NULL) { LPWSTR pwszAccountNameCopy;
pwszAccountNameCopy = (LPWSTR)CoTaskMemAlloc( (s_wcslen(pwszAccountName) + 1) * sizeof(WCHAR));
if (pwszAccountNameCopy == NULL) { return(E_OUTOFMEMORY); }
s_wcscpy(pwszAccountNameCopy, pwszAccountName); *ppwszAccountName = pwszAccountNameCopy; }
return(hr); #else
return(SCHED_E_NO_SECURITY_SERVICES);
#endif // !defined(_CHICAGO)
}
//+----------------------------------------------------------------------------
//
// Member: CJob::IPersistFile::Save
//
// Synopsis: Save job properties to the job object. Upon successful save,
// if account credentials have been specified, set them via
// RPC to the service.
//
// Arguments: [pwszFileName] - if null, save to the previously loaded file.
// [fRemember] - if TRUE, the object becomes associated with
// the new filename.
//
// Notes: This member must now be split into two versions with the
// addition of security: one for the .dll in
// sched\client\job.cxx, and for the .exe in
// sched\svc_core\job.cxx. This was necessary as Save now
// includes client-side rpc code. A single version of this
// member would require the client-side rpc code to be included
// in the service.
//
// All OLE32 strings are UNICODE, including the filename passed
// in the IPersistFile methods. On Win9x, all file names must
// be in ANSI strings, thus the conversion and call to SaveP.
//
//-----------------------------------------------------------------------------
STDMETHODIMP CJob::Save(LPCOLESTR pwszFileName, BOOL fRemember) { HRESULT hr = S_OK;
#if defined(UNICODE)
//
// Always save fixed and variable length data, but Never alter the running
// instance count from the COM interface method.
//
hr = SaveP(pwszFileName, fRemember, SAVEP_VARIABLE_LENGTH_DATA);
#else
CHAR szFileName[MAX_PATH + 1];
if (pwszFileName != NULL) // If filename non-null, convert to ANSI
{ hr = UnicodeToAnsi(szFileName, pwszFileName, MAX_PATH + 1);
if (FAILED(hr)) { return STG_E_INVALIDNAME; } }
hr = SaveP(pwszFileName != NULL ? szFileName : NULL, fRemember, SAVEP_VARIABLE_LENGTH_DATA); #endif
if (FAILED(hr)) { return(hr); }
//
// If nested folders are allowed in the future, add code something
// like this:
//
//
// if (hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND))
// {
// //
// // Create folders as needed
// //
// hr = CreateFolders(pwszFileName, TRUE);
// if (FAILED(hr))
// {
// ERR_OUT("CJob::Save: CreateFolders", hr);
// return hr;
// }
// //
// // Try again
// //
// hr = pJob->SaveP(pwszFileName, fRemember, SAVEP_VARIABLE_LENGTH_DATA);
// }
//
//
// This operation is not supported locally on Win95, and for the first
// release of the scheduling agent, neither remotely from Win95 to NT.
//
#if !defined(_CHICAGO_)
//
// Now that job changes are completely saved, set security information,
// if specified. This order is important as the application name is tied
// to the credentials for security reasons. If the application changes,
// the existing credentials are invalidated.
//
// ** Important ** Maintain file save, security setting order!
//
if (IsFlagSet(JOB_I_FLAG_SET_ACCOUNT_INFO)) { //
// RPC to the server local to this job to fetch the account name
// associated with this job.
//
// First, figure out if this is a remote job. If so, fetch the server
// name on which the job resides.
//
// Also, if this code is executing on Win95, and the file name passed
// is NULL, the ANSI private filename data must be converted to
// unicode. Note, CJob::SaveP checks if m_ptszFileName is NULL. The
// member fails if this is the case.
//
WCHAR wszUNCPath[MAX_PATH + 1]; WCHAR * pwszFileNameLocal; WCHAR * pwszServerName; #if !defined(UNICODE)
WCHAR wszFileName[MAX_PATH + 1] = L""; #endif // UNICODE
if (pwszFileName == NULL) { #if !defined(UNICODE)
hr = AnsiToUnicode(wszFileName, m_ptszFileName, MAX_PATH + 1);
if (FAILED(hr)) { return(hr); } pwszFileNameLocal = wszFileName; #else
pwszFileNameLocal = m_ptszFileName; #endif // UNICODE
} else { pwszFileNameLocal = (WCHAR *)pwszFileName; }
//
// Fetch the server name associated with the network path. If the path
// is local, the server name returned will be NULL.
//
hr = GetServerNameFromPath(pwszFileNameLocal, (MAX_PATH + 1) * sizeof(WCHAR), wszUNCPath, &pwszServerName);
if (FAILED(hr)) { return(hr); }
#if defined(_CHICAGO_)
//
// Local security operations are not supported on Win95.
//
if (pwszServerName == NULL) { return(SCHED_E_NO_SECURITY_SERVICES); } #endif // _CHICAGO_
//
// RPC to the service to set the account information.
//
// First, isolate the relative job name from the remaining path.
//
WCHAR * pwszRelativeFileName;
if (pwszFileNameLocal != NULL) { pwszRelativeFileName = wcsrchr(pwszFileNameLocal, L'\\');
if (pwszRelativeFileName != NULL) { pwszRelativeFileName++; } else { pwszRelativeFileName = pwszFileNameLocal; } }
RpcTryExcept { //
// Note: We pass the flags via RPC in order to let
// the server side do the access checks for the NULL
// password case. These checks could technically be
// done on the client side, but it's more convenient
// (and smaller codesize) to do it this way
//
hr = SASetAccountInformation(pwszServerName, pwszRelativeFileName, m_pAccountInfo->pwszAccount, m_pAccountInfo->pwszPassword, m_rgFlags); } RpcExcept(1) { DWORD Status = RpcExceptionCode(); schDebugOut((DEB_ERROR, "SetAccountInformation exception(0x%x)\n", Status)); hr = SchedMapRpcError(Status); } RpcEndExcept;
this->ClearFlag(JOB_I_FLAG_SET_ACCOUNT_INFO);
//
// NB : After successful save of the security information, the
// cached values are reset.
//
ResetAccountInfo(m_pAccountInfo); delete m_pAccountInfo; m_pAccountInfo = NULL; } #endif // !defined(_CHICAGO_)
return hr; }
//
// This operation is not supported locally on Win95, and for the first
// release of the scheduling agent, neither remotely from Win95 to NT.
//
#if !defined(_CHICAGO_)
//+----------------------------------------------------------------------------
//
// Function: ResetAccountInfo
//
// Synopsis: Simple helper to zero the password and deallocate struct
// JOB_ACCOUNT_INFO fields.
//
// Arguments: [pAccountInfo] -- Account info struct to reset.
//
// Returns: None.
//
// Notes: None.
//
//-----------------------------------------------------------------------------
void ResetAccountInfo(PJOB_ACCOUNT_INFO pAccountInfo) { delete pAccountInfo->pwszAccount; pAccountInfo->pwszAccount = NULL;
if (pAccountInfo->pwszPassword != NULL) { ZERO_PASSWORD(pAccountInfo->pwszPassword); delete pAccountInfo->pwszPassword; pAccountInfo->pwszPassword = NULL; } } #endif // !defined(_CHICAGO_)
|