Source code of Windows XP (NT5)
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.

661 lines
18 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. #if !defined(_CHICAGO_)
  34. #include "network.hxx"
  35. #endif // !defined(_CHICAGO_)
  36. #include "misc.hxx"
  37. #include "job_cls.hxx"
  38. #include "debug.hxx"
  39. #if !defined(_CHICAGO_)
  40. #include "defines.hxx"
  41. #endif // !defined(_CHICAGO_)
  42. #if !defined(_CHICAGO_)
  43. #include "SASecRPC.h" // Get/SetAccountInformation RPC definition.
  44. #endif // !defined(_CHICAGO_)
  45. #if !defined(_CHICAGO_)
  46. typedef DWORD (WINAPI * PWNETGETUNIVERSALNAMEW)(LPCWSTR, DWORD, LPVOID,
  47. LPDWORD);
  48. PWNETGETUNIVERSALNAMEW gpWNetGetUniversalNameW = NULL;
  49. #endif // !defined(_CHICAGO_)
  50. HRESULT DisplayJobProperties(LPTSTR, ITask *);
  51. //
  52. // This operation is not supported locally on Win95, and for the first
  53. // release of the scheduling agent, neither remotely from Win95 to NT.
  54. //
  55. #if !defined(_CHICAGO_)
  56. void ResetAccountInfo(PJOB_ACCOUNT_INFO pAccountInfo);
  57. #endif // !defined(_CHICAGO_)
  58. //+----------------------------------------------------------------------------
  59. //
  60. // Member: CJob::ITask::EditWorkItem
  61. //
  62. // Synopsis: Invoke the edit job property sheet.
  63. //
  64. //-----------------------------------------------------------------------------
  65. STDMETHODIMP
  66. CJob::EditWorkItem(HWND hParent, DWORD dwReserved)
  67. {
  68. if (m_ptszFileName != NULL && m_ptszFileName[0] != TEXT('\0'))
  69. {
  70. return DisplayJobProperties(m_ptszFileName, (ITask *)this);
  71. }
  72. return STG_E_NOTFILEBASEDSTORAGE;
  73. }
  74. //+----------------------------------------------------------------------------
  75. //
  76. // CJob::IProvideTaskPage::GetPage method
  77. //
  78. //-----------------------------------------------------------------------------
  79. STDMETHODIMP
  80. I_GetTaskPage(
  81. ITask * pITask,
  82. TASKPAGE tpType,
  83. BOOL fPersistChanges,
  84. HPROPSHEETPAGE * phPage);
  85. STDMETHODIMP
  86. CJob::GetPage(
  87. TASKPAGE tpType,
  88. BOOL fPersistChanges,
  89. HPROPSHEETPAGE * phPage)
  90. {
  91. return I_GetTaskPage((ITask *)this, tpType, fPersistChanges, phPage);
  92. }
  93. //+----------------------------------------------------------------------------
  94. //
  95. // Member: CJob::ITask::SetAccountInformation
  96. //
  97. // Synopsis: Set the name and password of the account to be used for running
  98. // this job.
  99. //
  100. // Arguments: [pwszAccountName] -- Account name.
  101. // [pwszPassword] -- Account password.
  102. //
  103. // Returns: S_OK
  104. // E_INVALIDARG
  105. // E_OUTOFMEMORY
  106. //
  107. // Notes: Both strings are caller allocated and freed.
  108. //
  109. //-----------------------------------------------------------------------------
  110. STDMETHODIMP
  111. CJob::SetAccountInformation(LPCWSTR pwszAccountName,
  112. LPCWSTR pwszPassword)
  113. {
  114. TRACE(CJob, SetAccountInformation)
  115. if( NULL == pwszAccountName )
  116. {
  117. return E_INVALIDARG;
  118. }
  119. //
  120. // This operation is not supported locally on Win95, and for the first
  121. // release of the scheduling agent, neither remotely from Win95 to NT.
  122. //
  123. #if !defined(_CHICAGO_)
  124. HRESULT hr;
  125. //
  126. // Need to allocate the private data member structure containing copies
  127. // of the account arguments.
  128. //
  129. // Note, could allocate everything within a single buffer, but since
  130. // this operation is performed so rarely, it really isn't worth it.
  131. //
  132. PJOB_ACCOUNT_INFO pAccountInfo = new JOB_ACCOUNT_INFO;
  133. if (pAccountInfo == NULL)
  134. {
  135. return(E_OUTOFMEMORY);
  136. }
  137. pAccountInfo->pwszPassword = NULL;
  138. pAccountInfo->pwszAccount = new WCHAR[wcslen(pwszAccountName) + 1];
  139. if (pAccountInfo->pwszAccount != NULL)
  140. {
  141. wcscpy(pAccountInfo->pwszAccount, pwszAccountName);
  142. }
  143. else
  144. {
  145. hr = E_OUTOFMEMORY;
  146. goto ErrorExit;
  147. }
  148. if (pwszPassword != NULL)
  149. {
  150. pAccountInfo->pwszPassword = new WCHAR[wcslen(pwszPassword) + 1];
  151. if (pAccountInfo->pwszPassword != NULL)
  152. {
  153. wcscpy(pAccountInfo->pwszPassword, pwszPassword);
  154. }
  155. else
  156. {
  157. hr = E_OUTOFMEMORY;
  158. goto ErrorExit;
  159. }
  160. }
  161. if (m_pAccountInfo != NULL)
  162. {
  163. ResetAccountInfo(m_pAccountInfo);
  164. delete m_pAccountInfo;
  165. }
  166. m_pAccountInfo = pAccountInfo;
  167. //
  168. // Setting this flag will result in the RPC call to set the account
  169. // information on object save (IPersistFile::Save()).
  170. //
  171. this->SetFlag(JOB_I_FLAG_SET_ACCOUNT_INFO);
  172. return(S_OK);
  173. ErrorExit:
  174. if (pAccountInfo != NULL)
  175. {
  176. ResetAccountInfo(pAccountInfo);
  177. delete pAccountInfo;
  178. }
  179. return(hr);
  180. #else
  181. return(SCHED_E_NO_SECURITY_SERVICES);
  182. #endif // !defined(_CHICAGO)
  183. }
  184. //+----------------------------------------------------------------------------
  185. //
  186. // Member: CJob::ITask::GetAccountInformation
  187. //
  188. // Synopsis: Get the name of the account to be used for this job.
  189. //
  190. // Arguments: [ppwszAccountName] - the returned string buffer
  191. //
  192. // Returns: HRESULTS
  193. //
  194. // Notes: The string is callee allocated and caller freed with
  195. // CoTaskMemFree.
  196. //
  197. //-----------------------------------------------------------------------------
  198. STDMETHODIMP
  199. CJob::GetAccountInformation(LPWSTR * ppwszAccountName)
  200. {
  201. TRACE3(CJob, GetAccountInformation)
  202. //
  203. // This operation is not supported locally on Win95, and for the first
  204. // release of the scheduling agent, neither remotely from Win95 to NT.
  205. //
  206. #if !defined(_CHICAGO_)
  207. HRESULT hr;
  208. //
  209. // Unexpected, but possible should the caller CoCreateInstance a new
  210. // job, then call this member w/o IPersistFile::Load/Save.
  211. //
  212. if (m_ptszFileName == NULL)
  213. {
  214. schDebugOut((DEB_ERROR,
  215. "GetAccountInformation called with no filename\n"));
  216. return(E_UNEXPECTED);
  217. }
  218. //
  219. // Return cached account name. If it hasn't been obtained, we'll
  220. // need to RPC to the server to get it.
  221. //
  222. WCHAR wszAccountName[MAX_USERNAME + 1];
  223. WCHAR * pwszAccountName = NULL;
  224. if (m_pAccountInfo == NULL)
  225. {
  226. //
  227. // RPC to the server local to this job to fetch the account name
  228. // associated with this job.
  229. //
  230. // First, figure out if this is a remote job. If so, fetch the server
  231. // name on which the job resides.
  232. //
  233. WCHAR wszFileName[MAX_PATH + 1] = L"";
  234. WCHAR wszUNCPath[MAX_PATH + 1];
  235. WCHAR * pwszFileName;
  236. WCHAR * pwszServerName;
  237. #if !defined(UNICODE)
  238. HRESULT hr = AnsiToUnicode(wszFileName, m_ptszFileName, MAX_PATH+1);
  239. if (FAILED(hr))
  240. {
  241. return E_INVALIDARG;
  242. }
  243. pwszFileName = wszFileName;
  244. #else
  245. pwszFileName = m_ptszFileName;
  246. #endif // UNICODE
  247. //
  248. // Fetch the server name associated with the network path. If the path
  249. // is local, the server name returned will be NULL.
  250. //
  251. hr = GetServerNameFromPath(pwszFileName,
  252. (MAX_PATH + 1) * sizeof(WCHAR),
  253. wszUNCPath,
  254. &pwszServerName);
  255. if (FAILED(hr))
  256. {
  257. return(hr);
  258. }
  259. #if defined(_CHICAGO_)
  260. //
  261. // Local security operations are not supported on Win95.
  262. //
  263. if (pwszServerName == NULL)
  264. {
  265. return(SCHED_E_NO_SECURITY_SERVICES);
  266. }
  267. #endif // _CHICAGO_
  268. //
  269. // RPC to the service to fetch the account name.
  270. //
  271. // First, isolate the relative job name from the remaining path.
  272. //
  273. WCHAR * pwszRelativeFileName;
  274. if (pwszFileName != NULL)
  275. {
  276. pwszRelativeFileName = wcsrchr(pwszFileName, L'\\');
  277. if (pwszRelativeFileName != NULL)
  278. {
  279. pwszRelativeFileName++;
  280. }
  281. else
  282. {
  283. pwszRelativeFileName = pwszFileName;
  284. }
  285. }
  286. DWORD ccAccountName = MAX_USERNAME;
  287. RpcTryExcept
  288. {
  289. hr = SAGetAccountInformation(pwszServerName,
  290. pwszRelativeFileName,
  291. ccAccountName,
  292. wszAccountName);
  293. }
  294. RpcExcept(1)
  295. {
  296. DWORD Status = RpcExceptionCode();
  297. schDebugOut((DEB_ERROR,
  298. "GetAccountInformation exception(0x%x)\n",
  299. Status));
  300. hr = SchedMapRpcError(Status);
  301. }
  302. RpcEndExcept;
  303. if (SUCCEEDED(hr))
  304. {
  305. pwszAccountName = wszAccountName;
  306. }
  307. }
  308. else
  309. {
  310. schAssert(m_pAccountInfo->pwszAccount != NULL);
  311. pwszAccountName = m_pAccountInfo->pwszAccount;
  312. hr = S_OK;
  313. }
  314. //
  315. // Allocate returned name.
  316. //
  317. if (pwszAccountName != NULL)
  318. {
  319. LPWSTR pwszAccountNameCopy;
  320. pwszAccountNameCopy = (LPWSTR)CoTaskMemAlloc(
  321. (s_wcslen(pwszAccountName) + 1) * sizeof(WCHAR));
  322. if (pwszAccountNameCopy == NULL)
  323. {
  324. return(E_OUTOFMEMORY);
  325. }
  326. s_wcscpy(pwszAccountNameCopy, pwszAccountName);
  327. *ppwszAccountName = pwszAccountNameCopy;
  328. }
  329. return(hr);
  330. #else
  331. return(SCHED_E_NO_SECURITY_SERVICES);
  332. #endif // !defined(_CHICAGO)
  333. }
  334. //+----------------------------------------------------------------------------
  335. //
  336. // Member: CJob::IPersistFile::Save
  337. //
  338. // Synopsis: Save job properties to the job object. Upon successful save,
  339. // if account credentials have been specified, set them via
  340. // RPC to the service.
  341. //
  342. // Arguments: [pwszFileName] - if null, save to the previously loaded file.
  343. // [fRemember] - if TRUE, the object becomes associated with
  344. // the new filename.
  345. //
  346. // Notes: This member must now be split into two versions with the
  347. // addition of security: one for the .dll in
  348. // sched\client\job.cxx, and for the .exe in
  349. // sched\svc_core\job.cxx. This was necessary as Save now
  350. // includes client-side rpc code. A single version of this
  351. // member would require the client-side rpc code to be included
  352. // in the service.
  353. //
  354. // All OLE32 strings are UNICODE, including the filename passed
  355. // in the IPersistFile methods. On Win9x, all file names must
  356. // be in ANSI strings, thus the conversion and call to SaveP.
  357. //
  358. //-----------------------------------------------------------------------------
  359. STDMETHODIMP
  360. CJob::Save(LPCOLESTR pwszFileName, BOOL fRemember)
  361. {
  362. HRESULT hr = S_OK;
  363. #if defined(UNICODE)
  364. //
  365. // Always save fixed and variable length data, but Never alter the running
  366. // instance count from the COM interface method.
  367. //
  368. hr = SaveP(pwszFileName, fRemember, SAVEP_VARIABLE_LENGTH_DATA);
  369. #else
  370. CHAR szFileName[MAX_PATH + 1];
  371. if (pwszFileName != NULL) // If filename non-null, convert to ANSI
  372. {
  373. hr = UnicodeToAnsi(szFileName, pwszFileName, MAX_PATH + 1);
  374. if (FAILED(hr))
  375. {
  376. return STG_E_INVALIDNAME;
  377. }
  378. }
  379. hr = SaveP(pwszFileName != NULL ? szFileName : NULL,
  380. fRemember,
  381. SAVEP_VARIABLE_LENGTH_DATA);
  382. #endif
  383. if (FAILED(hr))
  384. {
  385. return(hr);
  386. }
  387. //
  388. // If nested folders are allowed in the future, add code something
  389. // like this:
  390. //
  391. //
  392. // if (hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND))
  393. // {
  394. // //
  395. // // Create folders as needed
  396. // //
  397. // hr = CreateFolders(pwszFileName, TRUE);
  398. // if (FAILED(hr))
  399. // {
  400. // ERR_OUT("CJob::Save: CreateFolders", hr);
  401. // return hr;
  402. // }
  403. // //
  404. // // Try again
  405. // //
  406. // hr = pJob->SaveP(pwszFileName, fRemember, SAVEP_VARIABLE_LENGTH_DATA);
  407. // }
  408. //
  409. //
  410. // This operation is not supported locally on Win95, and for the first
  411. // release of the scheduling agent, neither remotely from Win95 to NT.
  412. //
  413. #if !defined(_CHICAGO_)
  414. //
  415. // Now that job changes are completely saved, set security information,
  416. // if specified. This order is important as the application name is tied
  417. // to the credentials for security reasons. If the application changes,
  418. // the existing credentials are invalidated.
  419. //
  420. // ** Important ** Maintain file save, security setting order!
  421. //
  422. if (IsFlagSet(JOB_I_FLAG_SET_ACCOUNT_INFO))
  423. {
  424. //
  425. // RPC to the server local to this job to fetch the account name
  426. // associated with this job.
  427. //
  428. // First, figure out if this is a remote job. If so, fetch the server
  429. // name on which the job resides.
  430. //
  431. // Also, if this code is executing on Win95, and the file name passed
  432. // is NULL, the ANSI private filename data must be converted to
  433. // unicode. Note, CJob::SaveP checks if m_ptszFileName is NULL. The
  434. // member fails if this is the case.
  435. //
  436. WCHAR wszUNCPath[MAX_PATH + 1];
  437. WCHAR * pwszFileNameLocal;
  438. WCHAR * pwszServerName;
  439. #if !defined(UNICODE)
  440. WCHAR wszFileName[MAX_PATH + 1] = L"";
  441. #endif // UNICODE
  442. if (pwszFileName == NULL)
  443. {
  444. #if !defined(UNICODE)
  445. hr = AnsiToUnicode(wszFileName, m_ptszFileName, MAX_PATH + 1);
  446. if (FAILED(hr))
  447. {
  448. return(hr);
  449. }
  450. pwszFileNameLocal = wszFileName;
  451. #else
  452. pwszFileNameLocal = m_ptszFileName;
  453. #endif // UNICODE
  454. }
  455. else
  456. {
  457. pwszFileNameLocal = (WCHAR *)pwszFileName;
  458. }
  459. //
  460. // Fetch the server name associated with the network path. If the path
  461. // is local, the server name returned will be NULL.
  462. //
  463. hr = GetServerNameFromPath(pwszFileNameLocal,
  464. (MAX_PATH + 1) * sizeof(WCHAR),
  465. wszUNCPath,
  466. &pwszServerName);
  467. if (FAILED(hr))
  468. {
  469. return(hr);
  470. }
  471. #if defined(_CHICAGO_)
  472. //
  473. // Local security operations are not supported on Win95.
  474. //
  475. if (pwszServerName == NULL)
  476. {
  477. return(SCHED_E_NO_SECURITY_SERVICES);
  478. }
  479. #endif // _CHICAGO_
  480. //
  481. // RPC to the service to set the account information.
  482. //
  483. // First, isolate the relative job name from the remaining path.
  484. //
  485. WCHAR * pwszRelativeFileName;
  486. if (pwszFileNameLocal != NULL)
  487. {
  488. pwszRelativeFileName = wcsrchr(pwszFileNameLocal, L'\\');
  489. if (pwszRelativeFileName != NULL)
  490. {
  491. pwszRelativeFileName++;
  492. }
  493. else
  494. {
  495. pwszRelativeFileName = pwszFileNameLocal;
  496. }
  497. }
  498. RpcTryExcept
  499. {
  500. //
  501. // Note: We pass the flags via RPC in order to let
  502. // the server side do the access checks for the NULL
  503. // password case. These checks could technically be
  504. // done on the client side, but it's more convenient
  505. // (and smaller codesize) to do it this way
  506. //
  507. hr = SASetAccountInformation(pwszServerName,
  508. pwszRelativeFileName,
  509. m_pAccountInfo->pwszAccount,
  510. m_pAccountInfo->pwszPassword,
  511. m_rgFlags);
  512. }
  513. RpcExcept(1)
  514. {
  515. DWORD Status = RpcExceptionCode();
  516. schDebugOut((DEB_ERROR,
  517. "SetAccountInformation exception(0x%x)\n",
  518. Status));
  519. hr = SchedMapRpcError(Status);
  520. }
  521. RpcEndExcept;
  522. this->ClearFlag(JOB_I_FLAG_SET_ACCOUNT_INFO);
  523. //
  524. // NB : After successful save of the security information, the
  525. // cached values are reset.
  526. //
  527. ResetAccountInfo(m_pAccountInfo);
  528. delete m_pAccountInfo;
  529. m_pAccountInfo = NULL;
  530. }
  531. #endif // !defined(_CHICAGO_)
  532. return hr;
  533. }
  534. //
  535. // This operation is not supported locally on Win95, and for the first
  536. // release of the scheduling agent, neither remotely from Win95 to NT.
  537. //
  538. #if !defined(_CHICAGO_)
  539. //+----------------------------------------------------------------------------
  540. //
  541. // Function: ResetAccountInfo
  542. //
  543. // Synopsis: Simple helper to zero the password and deallocate struct
  544. // JOB_ACCOUNT_INFO fields.
  545. //
  546. // Arguments: [pAccountInfo] -- Account info struct to reset.
  547. //
  548. // Returns: None.
  549. //
  550. // Notes: None.
  551. //
  552. //-----------------------------------------------------------------------------
  553. void
  554. ResetAccountInfo(PJOB_ACCOUNT_INFO pAccountInfo)
  555. {
  556. delete pAccountInfo->pwszAccount;
  557. pAccountInfo->pwszAccount = NULL;
  558. if (pAccountInfo->pwszPassword != NULL)
  559. {
  560. ZERO_PASSWORD(pAccountInfo->pwszPassword);
  561. delete pAccountInfo->pwszPassword;
  562. pAccountInfo->pwszPassword = NULL;
  563. }
  564. }
  565. #endif // !defined(_CHICAGO_)