Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

541 lines
16 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1996.
  5. //
  6. // File: job.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes: None.
  11. //
  12. // Functions:
  13. //
  14. // History: 14-Mar-96 EricB created
  15. // 21-Jun-96 MarkBl Renamed from jobedit.cxx since now Save() &
  16. // Get/SetAccountInformation members require
  17. // client-side rpc. Their implementations must
  18. // reside here so we don't have to include the
  19. // client-side RPC in the service. Also added
  20. // Get/SetAccountInformation members.
  21. //
  22. // Notes: Disabled security code completely for Win95. This will be
  23. // enabled in the next release of the scheduling agent.
  24. //
  25. // BUGBUG : The classes should be split into a core base class,
  26. // then have an OLE-supporting class inherit from it.
  27. // The core class would exist in the service. The sub-
  28. // class in the dll.
  29. //
  30. //____________________________________________________________________________
  31. #include "..\pch\headers.hxx"
  32. #pragma hdrstop
  33. #include "network.hxx"
  34. #include "misc.hxx"
  35. #include "job_cls.hxx"
  36. #include "debug.hxx"
  37. #include "defines.hxx"
  38. #include "SASecRPC.h" // Get/SetAccountInformation RPC definition.
  39. #include <StrSafe.h>
  40. typedef DWORD (WINAPI * PWNETGETUNIVERSALNAMEW)(LPCWSTR, DWORD, LPVOID,
  41. LPDWORD);
  42. PWNETGETUNIVERSALNAMEW gpWNetGetUniversalNameW = NULL;
  43. HRESULT DisplayJobProperties(LPTSTR, ITask *);
  44. //
  45. // This operation is not supported locally on Win95, and for the first
  46. // release of the scheduling agent, neither remotely from Win95 to NT.
  47. //
  48. void ResetAccountInfo(PJOB_ACCOUNT_INFO pAccountInfo);
  49. //+----------------------------------------------------------------------------
  50. //
  51. // Member: CJob::ITask::EditWorkItem
  52. //
  53. // Synopsis: Invoke the edit job property sheet.
  54. //
  55. //-----------------------------------------------------------------------------
  56. STDMETHODIMP
  57. CJob::EditWorkItem(HWND hParent, DWORD dwReserved)
  58. {
  59. if (m_ptszFileName != NULL && m_ptszFileName[0] != TEXT('\0'))
  60. {
  61. return DisplayJobProperties(m_ptszFileName, (ITask *)this);
  62. }
  63. return STG_E_NOTFILEBASEDSTORAGE;
  64. }
  65. //+----------------------------------------------------------------------------
  66. //
  67. // CJob::IProvideTaskPage::GetPage method
  68. //
  69. //-----------------------------------------------------------------------------
  70. STDMETHODIMP
  71. I_GetTaskPage(
  72. ITask * pITask,
  73. TASKPAGE tpType,
  74. BOOL fPersistChanges,
  75. HPROPSHEETPAGE * phPage);
  76. STDMETHODIMP
  77. CJob::GetPage(
  78. TASKPAGE tpType,
  79. BOOL fPersistChanges,
  80. HPROPSHEETPAGE * phPage)
  81. {
  82. return I_GetTaskPage((ITask *)this, tpType, fPersistChanges, phPage);
  83. }
  84. //+----------------------------------------------------------------------------
  85. //
  86. // Member: CJob::ITask::SetAccountInformation
  87. //
  88. // Synopsis: Set the name and password of the account to be used for running
  89. // this job.
  90. //
  91. // Arguments: [pwszAccountName] -- Account name.
  92. // [pwszPassword] -- Account password.
  93. //
  94. // Returns: S_OK
  95. // E_INVALIDARG
  96. // E_OUTOFMEMORY
  97. //
  98. // Notes: Both strings are caller allocated and freed.
  99. //
  100. //-----------------------------------------------------------------------------
  101. STDMETHODIMP
  102. CJob::SetAccountInformation(LPCWSTR pwszAccountName,
  103. LPCWSTR pwszPassword)
  104. {
  105. TRACE(CJob, SetAccountInformation)
  106. if( NULL == pwszAccountName )
  107. {
  108. return E_INVALIDARG;
  109. }
  110. //
  111. // This operation is not supported locally on Win95, and for the first
  112. // release of the scheduling agent, neither remotely from Win95 to NT.
  113. //
  114. HRESULT hr;
  115. //
  116. // Need to allocate the private data member structure containing copies
  117. // of the account arguments.
  118. //
  119. // Note, could allocate everything within a single buffer, but since
  120. // this operation is performed so rarely, it really isn't worth it.
  121. //
  122. PJOB_ACCOUNT_INFO pAccountInfo = new JOB_ACCOUNT_INFO;
  123. if (pAccountInfo == NULL)
  124. {
  125. return(E_OUTOFMEMORY);
  126. }
  127. pAccountInfo->pwszPassword = NULL;
  128. size_t acctLength = wcslen(pwszAccountName) + 1;
  129. pAccountInfo->pwszAccount = new WCHAR[acctLength];
  130. if (pAccountInfo->pwszAccount != NULL)
  131. {
  132. StringCchCopy(pAccountInfo->pwszAccount, acctLength, pwszAccountName);
  133. }
  134. else
  135. {
  136. hr = E_OUTOFMEMORY;
  137. goto ErrorExit;
  138. }
  139. if (pwszPassword != NULL)
  140. {
  141. size_t pwLength = wcslen(pwszPassword) + 1;
  142. pAccountInfo->pwszPassword = new WCHAR[pwLength];
  143. if (pAccountInfo->pwszPassword != NULL)
  144. {
  145. StringCchCopy(pAccountInfo->pwszPassword, pwLength, pwszPassword);
  146. }
  147. else
  148. {
  149. hr = E_OUTOFMEMORY;
  150. goto ErrorExit;
  151. }
  152. }
  153. if (m_pAccountInfo != NULL)
  154. {
  155. ResetAccountInfo(m_pAccountInfo);
  156. delete m_pAccountInfo;
  157. }
  158. m_pAccountInfo = pAccountInfo;
  159. //
  160. // Setting this flag will result in the RPC call to set the account
  161. // information on object save (IPersistFile::Save()).
  162. //
  163. this->SetFlag(JOB_I_FLAG_SET_ACCOUNT_INFO);
  164. return(S_OK);
  165. ErrorExit:
  166. if (pAccountInfo != NULL)
  167. {
  168. ResetAccountInfo(pAccountInfo);
  169. delete pAccountInfo;
  170. }
  171. return(hr);
  172. }
  173. //+----------------------------------------------------------------------------
  174. //
  175. // Member: CJob::ITask::GetAccountInformation
  176. //
  177. // Synopsis: Get the name of the account to be used for this job.
  178. //
  179. // Arguments: [ppwszAccountName] - the returned string buffer
  180. //
  181. // Returns: HRESULTS
  182. //
  183. // Notes: The string is callee allocated and caller freed with
  184. // CoTaskMemFree.
  185. //
  186. //-----------------------------------------------------------------------------
  187. STDMETHODIMP
  188. CJob::GetAccountInformation(LPWSTR * ppwszAccountName)
  189. {
  190. TRACE3(CJob, GetAccountInformation)
  191. //
  192. // This operation is not supported locally on Win95, and for the first
  193. // release of the scheduling agent, neither remotely from Win95 to NT.
  194. //
  195. HRESULT hr;
  196. //
  197. // Unexpected, but possible should the caller CoCreateInstance a new
  198. // job, then call this member w/o IPersistFile::Load/Save.
  199. //
  200. if (m_ptszFileName == NULL)
  201. {
  202. schDebugOut((DEB_ERROR,
  203. "GetAccountInformation called with no filename\n"));
  204. return(E_UNEXPECTED);
  205. }
  206. //
  207. // Return cached account name. If it hasn't been obtained, we'll
  208. // need to RPC to the server to get it.
  209. //
  210. WCHAR wszAccountName[MAX_USERNAME + 1];
  211. WCHAR * pwszAccountName = NULL;
  212. if (m_pAccountInfo == NULL)
  213. {
  214. //
  215. // RPC to the server local to this job to fetch the account name
  216. // associated with this job.
  217. //
  218. // First, figure out if this is a remote job. If so, fetch the server
  219. // name on which the job resides.
  220. //
  221. WCHAR wszFileName[MAX_PATH + 1] = L"";
  222. WCHAR wszUNCPath[MAX_PATH + 1];
  223. WCHAR * pwszFileName;
  224. WCHAR * pwszServerName;
  225. pwszFileName = m_ptszFileName;
  226. //
  227. // Fetch the server name associated with the network path. If the path
  228. // is local, the server name returned will be NULL.
  229. //
  230. hr = GetServerNameFromPath(pwszFileName,
  231. (MAX_PATH + 1) * sizeof(WCHAR),
  232. wszUNCPath,
  233. &pwszServerName);
  234. if (FAILED(hr))
  235. {
  236. return(hr);
  237. }
  238. //
  239. // RPC to the service to fetch the account name.
  240. //
  241. // First, isolate the relative job name from the remaining path.
  242. //
  243. WCHAR * pwszRelativeFileName;
  244. if (pwszFileName != NULL)
  245. {
  246. pwszRelativeFileName = wcsrchr(pwszFileName, L'\\');
  247. if (pwszRelativeFileName != NULL)
  248. {
  249. pwszRelativeFileName++;
  250. }
  251. else
  252. {
  253. pwszRelativeFileName = pwszFileName;
  254. }
  255. }
  256. DWORD ccAccountName = MAX_USERNAME;
  257. RpcTryExcept
  258. {
  259. hr = SAGetAccountInformation(pwszServerName,
  260. pwszRelativeFileName,
  261. ccAccountName,
  262. wszAccountName);
  263. }
  264. RpcExcept(1)
  265. {
  266. DWORD Status = RpcExceptionCode();
  267. schDebugOut((DEB_ERROR,
  268. "GetAccountInformation exception(0x%x)\n",
  269. Status));
  270. hr = SchedMapRpcError(Status);
  271. }
  272. RpcEndExcept;
  273. if (SUCCEEDED(hr))
  274. {
  275. pwszAccountName = wszAccountName;
  276. }
  277. }
  278. else
  279. {
  280. schAssert(m_pAccountInfo->pwszAccount != NULL);
  281. pwszAccountName = m_pAccountInfo->pwszAccount;
  282. hr = S_OK;
  283. }
  284. //
  285. // Allocate returned name.
  286. //
  287. if (pwszAccountName != NULL)
  288. {
  289. LPWSTR pwszAccountNameCopy;
  290. size_t pwLength = (wcslen(pwszAccountName) + 1);
  291. pwszAccountNameCopy = (LPWSTR)CoTaskMemAlloc(
  292. pwLength * sizeof(WCHAR));
  293. if (pwszAccountNameCopy == NULL)
  294. {
  295. return(E_OUTOFMEMORY);
  296. }
  297. StringCchCopy(pwszAccountNameCopy, pwLength, pwszAccountName);
  298. *ppwszAccountName = pwszAccountNameCopy;
  299. }
  300. return(hr);
  301. }
  302. //+----------------------------------------------------------------------------
  303. //
  304. // Member: CJob::IPersistFile::Save
  305. //
  306. // Synopsis: Save job properties to the job object. Upon successful save,
  307. // if account credentials have been specified, set them via
  308. // RPC to the service.
  309. //
  310. // Arguments: [pwszFileName] - if null, save to the previously loaded file.
  311. // [fRemember] - if TRUE, the object becomes associated with
  312. // the new filename.
  313. //
  314. // Notes: This member must now be split into two versions with the
  315. // addition of security: one for the .dll in
  316. // sched\client\job.cxx, and for the .exe in
  317. // sched\svc_core\job.cxx. This was necessary as Save now
  318. // includes client-side rpc code. A single version of this
  319. // member would require the client-side rpc code to be included
  320. // in the service.
  321. //
  322. // All OLE32 strings are UNICODE, including the filename passed
  323. // in the IPersistFile methods.
  324. //
  325. //-----------------------------------------------------------------------------
  326. STDMETHODIMP
  327. CJob::Save(LPCOLESTR pwszFileName, BOOL fRemember)
  328. {
  329. HRESULT hr = S_OK;
  330. //
  331. // Always save fixed and variable length data, but Never alter the running
  332. // instance count from the COM interface method.
  333. //
  334. hr = SaveWithRetry(pwszFileName, fRemember, SAVEP_VARIABLE_LENGTH_DATA);
  335. if (FAILED(hr))
  336. {
  337. return(hr);
  338. }
  339. //
  340. // Now that job changes are completely saved, set security information,
  341. // if specified. This order is important as the application name is tied
  342. // to the credentials for security reasons. If the application changes,
  343. // the existing credentials are invalidated.
  344. //
  345. // ** Important ** Maintain file save, security setting order!
  346. //
  347. if (IsFlagSet(JOB_I_FLAG_SET_ACCOUNT_INFO))
  348. {
  349. //
  350. // RPC to the server local to this job to fetch the account name
  351. // associated with this job.
  352. //
  353. // First, figure out if this is a remote job. If so, fetch the server
  354. // name on which the job resides.
  355. //
  356. WCHAR wszUNCPath[MAX_PATH + 1];
  357. WCHAR * pwszFileNameLocal;
  358. WCHAR * pwszServerName;
  359. if (pwszFileName == NULL)
  360. {
  361. pwszFileNameLocal = m_ptszFileName;
  362. }
  363. else
  364. {
  365. pwszFileNameLocal = (WCHAR *)pwszFileName;
  366. }
  367. //
  368. // Fetch the server name associated with the network path. If the path
  369. // is local, the server name returned will be NULL.
  370. //
  371. hr = GetServerNameFromPath(pwszFileNameLocal,
  372. (MAX_PATH + 1) * sizeof(WCHAR),
  373. wszUNCPath,
  374. &pwszServerName);
  375. if (FAILED(hr))
  376. {
  377. return(hr);
  378. }
  379. //
  380. // RPC to the service to set the account information.
  381. //
  382. // First, isolate the relative job name from the remaining path.
  383. //
  384. WCHAR * pwszRelativeFileName;
  385. if (pwszFileNameLocal != NULL)
  386. {
  387. pwszRelativeFileName = wcsrchr(pwszFileNameLocal, L'\\');
  388. if (pwszRelativeFileName != NULL)
  389. {
  390. pwszRelativeFileName++;
  391. }
  392. else
  393. {
  394. pwszRelativeFileName = pwszFileNameLocal;
  395. }
  396. }
  397. RpcTryExcept
  398. {
  399. //
  400. // Note: We pass the flags via RPC in order to let
  401. // the server side do the access checks for the NULL
  402. // password case. These checks could technically be
  403. // done on the client side, but it's more convenient
  404. // (and smaller codesize) to do it this way
  405. //
  406. hr = SASetAccountInformation(pwszServerName,
  407. pwszRelativeFileName,
  408. m_pAccountInfo->pwszAccount,
  409. m_pAccountInfo->pwszPassword,
  410. m_rgFlags);
  411. }
  412. RpcExcept(1)
  413. {
  414. DWORD Status = RpcExceptionCode();
  415. schDebugOut((DEB_ERROR,
  416. "SetAccountInformation exception(0x%x)\n",
  417. Status));
  418. hr = SchedMapRpcError(Status);
  419. }
  420. RpcEndExcept;
  421. this->ClearFlag(JOB_I_FLAG_SET_ACCOUNT_INFO);
  422. //
  423. // NB : After successful save of the security information, the
  424. // cached values are reset.
  425. //
  426. ResetAccountInfo(m_pAccountInfo);
  427. delete m_pAccountInfo;
  428. m_pAccountInfo = NULL;
  429. }
  430. return hr;
  431. }
  432. //
  433. // This operation is not supported locally on Win95, and for the first
  434. // release of the scheduling agent, neither remotely from Win95 to NT.
  435. //
  436. //+----------------------------------------------------------------------------
  437. //
  438. // Function: ResetAccountInfo
  439. //
  440. // Synopsis: Simple helper to zero the password and deallocate struct
  441. // JOB_ACCOUNT_INFO fields.
  442. //
  443. // Arguments: [pAccountInfo] -- Account info struct to reset.
  444. //
  445. // Returns: None.
  446. //
  447. // Notes: None.
  448. //
  449. //-----------------------------------------------------------------------------
  450. void
  451. ResetAccountInfo(PJOB_ACCOUNT_INFO pAccountInfo)
  452. {
  453. delete pAccountInfo->pwszAccount;
  454. pAccountInfo->pwszAccount = NULL;
  455. if (pAccountInfo->pwszPassword != NULL)
  456. {
  457. ZERO_PASSWORD(pAccountInfo->pwszPassword);
  458. delete pAccountInfo->pwszPassword;
  459. pAccountInfo->pwszPassword = NULL;
  460. }
  461. }