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.

971 lines
26 KiB

  1. /*++
  2. Copyright (c) 1990 - 1995 Microsoft Corporation
  3. Module Name:
  4. net.c
  5. Abstract:
  6. This module provides all the network stuuf for localspl
  7. Author:
  8. Dave Snipp (DaveSn) 15-Mar-1991
  9. Notes:
  10. We just need to get the winspool printer name associated with a given
  11. queue name. The SHARE_INFO_2 structure has a shi2_path field that would
  12. be nice to use, but NetShareGetInfo level 2 is privileged. So, by
  13. DaveSn's arm twisting and agreement with windows/spooler/localspl/net.c,
  14. we're going to use the shi1_remark field for this. This allows us to
  15. do NetShareGetInfo level 1, which is not privileged.
  16. This has been fixed by allowing OpenPrinter to succeed on share names.
  17. If there is no comment, we put the printer name in as the remark
  18. (for graceful upgrades from pre-PPC).
  19. Revision History:
  20. Jun 93 mattfe pIniSpooler
  21. --*/
  22. #define UNICODE 1
  23. #define NOMINMAX
  24. #include <precomp.h>
  25. #pragma hdrstop
  26. #include "clusspl.h"
  27. #ifdef DBG_SHARE
  28. #include <messages.h>
  29. #endif
  30. NET_API_STATUS (*pfnNetShareAdd)();
  31. NET_API_STATUS (*pfnNetShareSetInfo)();
  32. NET_API_STATUS (*pfnNetShareDel)();
  33. NET_API_STATUS (*pfnNetServerEnum)();
  34. NET_API_STATUS (*pfnNetWkstaUserGetInfo)();
  35. NET_API_STATUS (*pfnNetApiBufferFree)();
  36. NET_API_STATUS (*pfnNetAlertRaiseEx)();
  37. NET_API_STATUS (*pfnNetShareGetInfo)(LPWSTR, LPWSTR, DWORD, LPBYTE *);
  38. extern SHARE_INFO_2 PrintShareInfo;
  39. extern SHARE_INFO_2 PrtProcsShareInfo;
  40. BOOL
  41. InitializeNet(
  42. VOID
  43. )
  44. {
  45. HANDLE hNetApi;
  46. UINT uOldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  47. hNetApi = LoadLibrary(TEXT("netapi32.dll"));
  48. SetErrorMode(uOldErrorMode);
  49. if ( !hNetApi )
  50. return FALSE;
  51. pfnNetShareAdd = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetShareAdd");
  52. pfnNetShareSetInfo = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetShareSetInfo");
  53. pfnNetShareDel = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetShareDel");
  54. pfnNetServerEnum = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetServerEnum");
  55. pfnNetWkstaUserGetInfo = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetWkstaUserGetInfo");
  56. pfnNetApiBufferFree = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetApiBufferFree");
  57. pfnNetAlertRaiseEx = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetAlertRaiseEx");
  58. pfnNetShareGetInfo = (NET_API_STATUS (*)(LPWSTR, LPWSTR, DWORD, LPBYTE *))GetProcAddress(hNetApi, "NetShareGetInfo");
  59. if ( pfnNetShareAdd == NULL ||
  60. pfnNetShareSetInfo == NULL ||
  61. pfnNetShareDel == NULL ||
  62. pfnNetServerEnum == NULL ||
  63. pfnNetWkstaUserGetInfo == NULL ||
  64. pfnNetApiBufferFree == NULL ||
  65. pfnNetAlertRaiseEx == NULL ||
  66. pfnNetShareGetInfo == NULL) {
  67. return FALSE;
  68. }
  69. return TRUE;
  70. }
  71. BOOL
  72. SetPrinterShareInfo(
  73. PINIPRINTER pIniPrinter
  74. )
  75. /*++
  76. Routine Description:
  77. Sets the share information about a printer.
  78. Note: This does not update the share path. We need to
  79. delete and re-create the share in order to change the path.
  80. Arguments:
  81. pIniPrinter - Printer that needs to be updated.
  82. Return Value:
  83. TRUE - Success
  84. FALSE - Failed
  85. --*/
  86. {
  87. SHARE_INFO_502 ShareInfo;
  88. HANDLE hToken;
  89. PSECURITY_DESCRIPTOR pShareSecurityDescriptor = NULL;
  90. DWORD ParmError, rc;
  91. SplInSem();
  92. pShareSecurityDescriptor = MapPrinterSDToShareSD(pIniPrinter->pSecurityDescriptor);
  93. if ( !pShareSecurityDescriptor ) {
  94. rc = ERROR_INVALID_SECURITY_DESCR;
  95. goto Cleanup;
  96. }
  97. ZeroMemory((LPVOID)&ShareInfo, sizeof(ShareInfo));
  98. ShareInfo.shi502_netname = pIniPrinter->pShareName;
  99. ShareInfo.shi502_type = STYPE_PRINTQ;
  100. ShareInfo.shi502_permissions = 0;
  101. ShareInfo.shi502_max_uses = SHI_USES_UNLIMITED;
  102. ShareInfo.shi502_current_uses = SHI_USES_UNLIMITED;
  103. ShareInfo.shi502_passwd = NULL;
  104. ShareInfo.shi502_security_descriptor = pShareSecurityDescriptor;
  105. if ( pIniPrinter->pComment && pIniPrinter->pComment[0] ) {
  106. ShareInfo.shi502_remark = pIniPrinter->pComment;
  107. } else {
  108. ShareInfo.shi502_remark = pIniPrinter->pName;
  109. }
  110. INCPRINTERREF(pIniPrinter);
  111. LeaveSplSem();
  112. SplOutSem(); // We *MUST* be out of our semaphore as the NetShareSet may
  113. // come back and call spooler
  114. hToken = RevertToPrinterSelf();
  115. rc = (*pfnNetShareSetInfo)(NULL,
  116. ShareInfo.shi502_netname,
  117. 502,
  118. &ShareInfo,
  119. &ParmError);
  120. if ( rc ) {
  121. if (rc == NERR_NetNameNotFound)
  122. {
  123. //
  124. // This can happen deny all access to a shared printer, then
  125. // restart the computer. The server service tries to validate
  126. // it's share on startup, but since it has no access, it fails
  127. // and deletes it (it also wants a handle to the printer). When
  128. // you grant everyone access, we try to change the ACL on the
  129. // SMB share, but since it was deleted, we fail. Recreate
  130. // the share here.
  131. //
  132. EnterSplSem();
  133. if (!ShareThisPrinter(pIniPrinter,
  134. pIniPrinter->pShareName,
  135. TRUE)) {
  136. rc = GetLastError();
  137. } else {
  138. rc = ERROR_SUCCESS;
  139. }
  140. LeaveSplSem();
  141. }
  142. if (rc) {
  143. DBGMSG(DBG_WARNING,
  144. ("NetShareSetInfo/ShareThisPrinter failed: Error %d, Parm %d\n",
  145. rc, ParmError));
  146. SetLastError(rc);
  147. }
  148. }
  149. ImpersonatePrinterClient(hToken);
  150. EnterSplSem();
  151. DECPRINTERREF(pIniPrinter);
  152. Cleanup:
  153. SplInSem();
  154. LocalFree(pShareSecurityDescriptor);
  155. return rc == ERROR_SUCCESS;
  156. }
  157. BOOL
  158. ShareThisPrinter(
  159. PINIPRINTER pIniPrinter,
  160. LPWSTR pShareName,
  161. BOOL bShare
  162. )
  163. /*++
  164. Routine Description:
  165. Shares or UnShares a Printer.
  166. Note: this really should be two functions, and the return value
  167. is very confusing.
  168. Note: no validation of sharename is done. This must be done by
  169. callee, usually in ValidatePrinterInfo.
  170. Arguments:
  171. Return Value:
  172. Returns whether the printer is shared after this call.
  173. TRUE - Shared
  174. FALSE - Not Shared
  175. --*/
  176. {
  177. SHARE_INFO_502 ShareInfo = {0};
  178. DWORD rc;
  179. DWORD ParmError;
  180. PSECURITY_DESCRIPTOR pShareSecurityDescriptor = NULL;
  181. PINISPOOLER pIniSpooler = pIniPrinter->pIniSpooler;
  182. PSHARE_INFO_2 pShareInfo = (PSHARE_INFO_2)pIniSpooler->pDriversShareInfo;
  183. LPTSTR pszPrinterNameWithToken = NULL;
  184. HRESULT hr;
  185. HANDLE hToken;
  186. BOOL bReturn = FALSE;
  187. BOOL bSame = FALSE;
  188. LPWSTR pShareNameCopy = NULL;
  189. SPLASSERT( pIniPrinter->pName );
  190. SplInSem();
  191. pShareNameCopy = AllocSplStr(pShareName);
  192. if (!pShareNameCopy) {
  193. goto Done;
  194. }
  195. if ( bShare ) {
  196. if (!pfnNetShareAdd) {
  197. SetLastError( ERROR_PROC_NOT_FOUND );
  198. goto Done;
  199. }
  200. //
  201. // Share name validation has been moved into ValidatePrinterInfo.
  202. //
  203. if ((pShareSecurityDescriptor =
  204. MapPrinterSDToShareSD(pIniPrinter->pSecurityDescriptor)) == NULL) {
  205. SetLastError(ERROR_INVALID_SECURITY_DESCR);
  206. goto Done;
  207. }
  208. ShareInfo.shi502_netname = pShareNameCopy; // hplaser
  209. //
  210. // If there is a comment, use it; otherwise set the remark
  211. // to be the printer name.
  212. //
  213. // Note: if the printer name changes and we don't have a comment,
  214. // we will reshare the printer to update the remark.
  215. //
  216. if( pIniPrinter->pComment && pIniPrinter->pComment[0] ){
  217. ShareInfo.shi502_remark = pIniPrinter->pComment;
  218. } else {
  219. ShareInfo.shi502_remark = pIniPrinter->pName;
  220. }
  221. //
  222. // Use the fully qualifed name, and make sure it exists in
  223. // localspl by using LocalsplOnlyToken.
  224. //
  225. pszPrinterNameWithToken = pszGetPrinterName(
  226. pIniPrinter,
  227. pIniSpooler != pLocalIniSpooler,
  228. pszLocalsplOnlyToken );
  229. if( !pszPrinterNameWithToken ){
  230. goto Done;
  231. }
  232. ShareInfo.shi502_path = pszPrinterNameWithToken;
  233. ShareInfo.shi502_type = STYPE_PRINTQ;
  234. ShareInfo.shi502_permissions = 0;
  235. ShareInfo.shi502_max_uses = SHI_USES_UNLIMITED;
  236. ShareInfo.shi502_current_uses = SHI_USES_UNLIMITED;
  237. ShareInfo.shi502_passwd = NULL;
  238. ShareInfo.shi502_security_descriptor = pShareSecurityDescriptor;
  239. INCPRINTERREF(pIniPrinter);
  240. LeaveSplSem();
  241. //
  242. // We *MUST* be out of our semaphore as the NetShareAdd is
  243. // going to come round and call OpenPrinter.
  244. //
  245. SplOutSem();
  246. // Go add the Print Share
  247. hToken = RevertToPrinterSelf();
  248. //
  249. // Add a share for the spool\drivers directory:
  250. //
  251. if (rc = AddPrintShare(pIniSpooler))
  252. {
  253. if (rc != NERR_ServerNotStarted)
  254. {
  255. EnterSplSem();
  256. DECPRINTERREF(pIniPrinter);
  257. ImpersonatePrinterClient(hToken);
  258. SetLastError(rc);
  259. goto Done;
  260. }
  261. }
  262. #if DBG
  263. {
  264. WCHAR UserName[256];
  265. DWORD cbUserName=256;
  266. if (MODULE_DEBUG & DBG_SECURITY)
  267. GetUserName(UserName, &cbUserName);
  268. DBGMSG( DBG_SECURITY, ( "Calling NetShareAdd in context %ws\n", UserName ) );
  269. }
  270. #endif
  271. //
  272. // Add the printer share. Even if we failed above because Server Service is not started,
  273. // we still want to try. At boot time, it's worthwhile, since the Server service might
  274. // start accepting calls if it's done initializing.
  275. //
  276. rc = (*pfnNetShareAdd)(NULL, 502, (LPBYTE)&ShareInfo, &ParmError);
  277. //
  278. // Now take care of Web sharing. i.e. make sure wwwroot\sharename is created if the
  279. // printer is either local or masqurading. We cannot allow sharing of RPC connections.
  280. //
  281. if (pIniSpooler->SpoolerFlags & SPL_TYPE_LOCAL)
  282. {
  283. WebShare( pShareNameCopy );
  284. }
  285. //
  286. // If the return code is that the share already exists, then check to
  287. // see whether this share is to the same device, if it is we just
  288. // update the info on the share and return success.
  289. //
  290. if (rc == NERR_DuplicateShare) {
  291. if (ERROR_SUCCESS == CheckShareSame(pIniPrinter, &ShareInfo, &bSame) && bSame) {
  292. rc = ERROR_SUCCESS;
  293. }
  294. }
  295. //
  296. // Allow remote connections by calling into spoolsv and register the named pipe protocol.
  297. // The server keeps track of these calls, so doing it for each share is fine.
  298. // This is policy driven. The policy value is read in spoolsv.
  299. //
  300. if ((rc == ERROR_SUCCESS || rc == NERR_ServerNotStarted) &&
  301. FAILED(hr = AllowRemoteCalls()))
  302. {
  303. //
  304. // If we fail enabling the RPC named pipe, then just unshare the printer
  305. // and fail the call.
  306. // A futher attempt to share the printer will try again to enable the RPC pipe.
  307. //
  308. if (rc == ERROR_SUCCESS)
  309. {
  310. (*pfnNetShareDel)(NULL, ShareInfo.shi502_netname, 0);
  311. }
  312. rc = HRESULT_CODE(hr);
  313. }
  314. ImpersonatePrinterClient(hToken);
  315. EnterSplSem();
  316. DECPRINTERREF(pIniPrinter);
  317. if (ERROR_SUCCESS != rc) {
  318. DBGMSG( DBG_WARNING,
  319. ( "NetShareAdd failed %lx, Parameter %d\n",
  320. rc, ParmError ));
  321. if ((rc == ERROR_INVALID_PARAMETER) &&
  322. (ParmError == SHARE_NETNAME_PARMNUM)) {
  323. rc = ERROR_INVALID_SHARENAME;
  324. }
  325. SetLastError(rc);
  326. goto Done;
  327. }
  328. SPLASSERT( pIniPrinter != NULL);
  329. SPLASSERT( pIniPrinter->signature == IP_SIGNATURE);
  330. SPLASSERT( pIniPrinter->pIniSpooler != NULL);
  331. SPLASSERT( pIniPrinter->pIniSpooler->signature == ISP_SIGNATURE );
  332. CreateServerThread();
  333. //
  334. // The Printer is shared.
  335. //
  336. bReturn = TRUE;
  337. } else {
  338. if ( !pfnNetShareDel ) {
  339. bReturn = TRUE;
  340. goto Done;
  341. }
  342. INCPRINTERREF( pIniPrinter );
  343. LeaveSplSem();
  344. SplOutSem();
  345. hToken = RevertToPrinterSelf();
  346. rc = hToken ? ERROR_SUCCESS : GetLastError();
  347. if ( rc == ERROR_SUCCESS ) {
  348. rc = (*pfnNetShareDel)(NULL, pShareName, 0);
  349. // Now take care of Web unsharing. i.e. make sure wwwroot\sharename is deleted.
  350. if((pIniSpooler->SpoolerFlags & SPL_TYPE_LOCAL) && !(pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER))
  351. WebUnShare( pShareName );
  352. }
  353. if ( hToken ) {
  354. if ( !ImpersonatePrinterClient(hToken) && rc == ERROR_SUCCESS ) {
  355. rc = GetLastError();
  356. }
  357. }
  358. EnterSplSem();
  359. DECPRINTERREF(pIniPrinter);
  360. // The share may have been deleted manually, so don't worry
  361. // if we get NERR_NetNameNotFound:
  362. if ( rc && ( rc != NERR_NetNameNotFound )){
  363. DBGMSG(DBG_WARNING, ("NetShareDel failed %lx\n", rc));
  364. SetLastError( rc );
  365. bReturn = TRUE;
  366. }
  367. }
  368. Done:
  369. if( pShareSecurityDescriptor ){
  370. LocalFree(pShareSecurityDescriptor);
  371. }
  372. FreeSplStr(pszPrinterNameWithToken);
  373. FreeSplStr(pShareNameCopy);
  374. return bReturn;
  375. }
  376. /*--
  377. FillAlertStructWithJobStrings
  378. Allocates memory which has to be freed by caller.
  379. --*/
  380. HRESULT
  381. FillAlertStructWithJobStrings(
  382. PINIJOB pIniJob,
  383. PRINT_OTHER_INFO **pAlertInfo,
  384. PDWORD size
  385. )
  386. {
  387. HRESULT RetVal = E_FAIL;
  388. DWORD cchSizeToAlloc = 0;
  389. PBYTE pBuffer = NULL;
  390. LPWSTR psz = NULL;
  391. if (pIniJob && pAlertInfo && !(*pAlertInfo) && size)
  392. {
  393. //
  394. // Do this in the splSem so that no one can jo a SetJob While we're not looking
  395. //
  396. EnterSplSem();
  397. //
  398. // We don't know how big these strings are going to be in future, so size
  399. // them dynamically and alloc the structure to always be big enough.
  400. //
  401. cchSizeToAlloc = sizeof(PRINT_OTHER_INFO);
  402. //
  403. // We don't have to check some of these for existence, we know they exist.
  404. //
  405. cchSizeToAlloc += wcslen(pIniJob->pNotify) + 1 +
  406. wcslen(pIniJob->pIniPrinter->pName) + 1 +
  407. wcslen(pIniJob->pIniPrinter->pIniSpooler->pMachineName) + 1;
  408. if ( pIniJob->pDocument )
  409. {
  410. cchSizeToAlloc += wcslen(pIniJob->pDocument) + 1;
  411. }
  412. else
  413. {
  414. cchSizeToAlloc += 2;
  415. }
  416. if (pIniJob->pIniPrinter->pIniSpooler->bEnableNetPopupToComputer &&
  417. pIniJob->pMachineName)
  418. {
  419. cchSizeToAlloc += wcslen(pIniJob->pMachineName) + 1;
  420. }
  421. else
  422. {
  423. cchSizeToAlloc += wcslen(pIniJob->pNotify) + 1;
  424. }
  425. if ( pIniJob->pStatus )
  426. {
  427. cchSizeToAlloc += wcslen(pIniJob->pStatus) + 1;
  428. }
  429. else
  430. {
  431. cchSizeToAlloc += 2;
  432. }
  433. //
  434. // Alloc the memory
  435. //
  436. pBuffer = AllocSplMem(cchSizeToAlloc * sizeof(WCHAR));
  437. if ( pBuffer )
  438. {
  439. SIZE_T cchRemaining = cchSizeToAlloc;
  440. psz = (LPWSTR)ALERT_VAR_DATA((PRINT_OTHER_INFO *)pBuffer);
  441. //
  442. // We know that pBuffer will at a minimum be as big as a PRINT_OTHER_INFO.
  443. //
  444. cchRemaining -= sizeof(PRINT_OTHER_INFO);
  445. //
  446. // Do the copying
  447. //
  448. //
  449. // Computer Name
  450. //
  451. if(pIniJob->pIniPrinter->pIniSpooler->bEnableNetPopupToComputer &&
  452. pIniJob->pMachineName ){
  453. StrCchCopyMultipleStr(psz, cchRemaining, pIniJob->pMachineName, &psz, &cchRemaining);
  454. } else {
  455. StrCchCopyMultipleStr(psz, cchRemaining, pIniJob->pNotify, &psz, &cchRemaining);
  456. }
  457. //
  458. // UserName
  459. //
  460. StrCchCopyMultipleStr(psz, cchRemaining, pIniJob->pNotify, &psz, &cchRemaining);
  461. //
  462. // Document Name
  463. //
  464. if (pIniJob->pDocument)
  465. StrCchCopyMultipleStr(psz, cchRemaining, pIniJob->pDocument, &psz, &cchRemaining);
  466. else
  467. StrCchCopyMultipleStr(psz, cchRemaining, L"", &psz, &cchRemaining);
  468. //
  469. // Printer Name
  470. //
  471. StrCchCopyMultipleStr(psz, cchRemaining, pIniJob->pIniPrinter->pName, &psz, &cchRemaining);
  472. //
  473. // Server Name
  474. //
  475. StrCchCopyMultipleStr(psz, cchRemaining, pIniJob->pIniPrinter->pIniSpooler->pMachineName, &psz, &cchRemaining);
  476. //
  477. // Status_string
  478. // We should pass in other status strings for the other status errors, too.
  479. //
  480. if (pIniJob->pStatus && (pIniJob->Status & (JOB_ERROR | JOB_OFFLINE | JOB_PAPEROUT)))
  481. StrCchCopyMultipleStr(psz, cchRemaining, pIniJob->pStatus, &psz, &cchRemaining);
  482. else
  483. StrCchCopyMultipleStr(psz, cchRemaining, L"", &psz, &cchRemaining);
  484. //
  485. // Pass back the size and struct
  486. //
  487. *size = (DWORD)((PBYTE)psz - pBuffer);
  488. *pAlertInfo = (PRINT_OTHER_INFO *)pBuffer;
  489. RetVal = NOERROR;
  490. }
  491. else
  492. {
  493. RetVal = E_OUTOFMEMORY;
  494. }
  495. //
  496. // Leave the Spooler Semaphore
  497. //
  498. LeaveSplSem();
  499. }
  500. else
  501. {
  502. RetVal = E_INVALIDARG;
  503. }
  504. return RetVal;
  505. }
  506. VOID
  507. SendJobAlert(
  508. PINIJOB pIniJob
  509. )
  510. {
  511. PRINT_OTHER_INFO *pinfo = NULL;
  512. DWORD RetVal = ERROR_SUCCESS;
  513. DWORD Status;
  514. FILETIME FileTime;
  515. DWORD AlertSize = 0;
  516. //
  517. // Allow Hydra Sessions to be notified since they are remote
  518. //
  519. if( (USER_SHARED_DATA->SuiteMask & (1 << TerminalServer)) ) {
  520. if ( !pIniJob->pNotify ||
  521. !pIniJob->pNotify[0] ||
  522. !pIniJob->pIniPrinter->pIniSpooler->bEnableNetPopups ) {
  523. return;
  524. }
  525. }
  526. else {
  527. if ( !pIniJob->pNotify ||
  528. !pIniJob->pNotify[0] ||
  529. !(pIniJob->Status & JOB_REMOTE) ||
  530. !pIniJob->pIniPrinter->pIniSpooler->bEnableNetPopups ) {
  531. return;
  532. }
  533. }
  534. if ( FAILED(RetVal = FillAlertStructWithJobStrings(pIniJob, &pinfo, &AlertSize)))
  535. {
  536. if ( pinfo )
  537. FreeSplMem(pinfo);
  538. return;
  539. }
  540. pinfo->alrtpr_jobid = pIniJob->JobId;
  541. if (pIniJob->Status & (JOB_PRINTING | JOB_DESPOOLING | JOB_PRINTED | JOB_COMPLETE))
  542. Status = PRJOB_QS_PRINTING;
  543. else if (pIniJob->Status & JOB_PAUSED)
  544. Status = PRJOB_QS_PAUSED;
  545. else if (pIniJob->Status & JOB_SPOOLING)
  546. Status = PRJOB_QS_SPOOLING;
  547. else
  548. Status = PRJOB_QS_QUEUED;
  549. if (pIniJob->Status & (JOB_ERROR | JOB_OFFLINE | JOB_PAPEROUT)) {
  550. Status |= PRJOB_ERROR;
  551. if (pIniJob->Status & JOB_OFFLINE)
  552. Status |= PRJOB_DESTOFFLINE;
  553. if (pIniJob->Status & JOB_PAPEROUT)
  554. Status |= PRJOB_DESTNOPAPER;
  555. }
  556. if (pIniJob->Status & JOB_PRINTED)
  557. Status |= PRJOB_COMPLETE;
  558. else if (pIniJob->Status & JOB_PENDING_DELETION)
  559. Status |= PRJOB_DELETED;
  560. pinfo->alrtpr_status = Status;
  561. SystemTimeToFileTime( &pIniJob->Submitted, &FileTime );
  562. // FileTimeToDosDateTime(&FileTime, &DosDate, &DosTime);
  563. // pinfo->alrtpr_submitted = DosDate << 16 | DosTime;
  564. RtlTimeToSecondsSince1970((PLARGE_INTEGER) &FileTime,
  565. &pinfo->alrtpr_submitted);
  566. pinfo->alrtpr_size = pIniJob->Size;
  567. (*pfnNetAlertRaiseEx)(ALERT_PRINT_EVENT,
  568. (PBYTE) pinfo,
  569. AlertSize,
  570. L"SPOOLER");
  571. if ( pinfo )
  572. FreeSplMem(pinfo);
  573. }
  574. DWORD
  575. AddPrintShare(
  576. PINISPOOLER pIniSpooler
  577. )
  578. /*++
  579. Routine Description:
  580. Adds the print$ share based on pIniSpooler.
  581. Arguments:
  582. pIniSpooler - Share path is based on this information. pDriversShareInfo
  583. must be initialized before calling this routine.
  584. Return Value:
  585. TRUE - Success.
  586. FALSE - Failed. LastError set.
  587. --*/
  588. {
  589. DWORD rc;
  590. DWORD ParmError;
  591. SHARE_INFO_1501 ShareInfo1501 = {0};
  592. PSHARE_INFO_2 pShareInfo = (PSHARE_INFO_2)pIniSpooler->pDriversShareInfo;
  593. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  594. //
  595. // Assert that the path is identical to the local one since there's
  596. // only one print$ share. It should always be.
  597. //
  598. SPLASSERT( !lstrcmpi( pShareInfo->shi2_path,
  599. ((PSHARE_INFO_2)pLocalIniSpooler->pDriversShareInfo)->shi2_path ));
  600. rc = (*pfnNetShareAdd)( NULL,
  601. 2,
  602. (LPBYTE)pShareInfo,
  603. &ParmError );
  604. //
  605. // If it already exists, assume it is set up correctly.
  606. //
  607. if( rc == NERR_DuplicateShare ){
  608. return ERROR_SUCCESS;
  609. }
  610. //
  611. // If we didn't create the share, fail.
  612. //
  613. if( rc != ERROR_SUCCESS ){
  614. DBGMSG( DBG_WARN,
  615. ( "AddPrintShare: Error %d, Parm %d\n", rc, ParmError));
  616. return rc;
  617. }
  618. //
  619. // Set security on the newly created share.
  620. //
  621. // Bug 54844
  622. // If this fails, we've created the share but haven't put security
  623. // on it. Then since it exists, we'll never try and set it again.
  624. //
  625. pSecurityDescriptor = CreateDriversShareSecurityDescriptor();
  626. if( !pSecurityDescriptor ){
  627. return GetLastError();
  628. }
  629. ShareInfo1501.shi1501_security_descriptor = pSecurityDescriptor;
  630. rc = (*pfnNetShareSetInfo)( NULL,
  631. pShareInfo->shi2_netname,
  632. 1501,
  633. &ShareInfo1501,
  634. &ParmError );
  635. if( rc != ERROR_SUCCESS ){
  636. DBGMSG( DBG_WARN,
  637. ( "NetShareSetInfo failed: Error %d, Parm %d\n",
  638. rc, ParmError));
  639. }
  640. LocalFree(pSecurityDescriptor);
  641. return rc;
  642. }
  643. /*++
  644. Routine Name:
  645. CheckShareSame
  646. Routine Description:
  647. This checks to see whether the given share name is the same on both the
  648. local and remote machines.
  649. Arguments:
  650. pIniPrinter - The iniprinter for which we are adding the share.
  651. pShareInfo502 - The share info that we are attempting to add the share
  652. with.
  653. pbSame - The return parameter is TRUE if the shares were the same
  654. If the rc is not ERROR_SUCCESS, then the info could not
  655. be set.
  656. Return Value:
  657. An error code.
  658. --*/
  659. DWORD
  660. CheckShareSame(
  661. IN PINIPRINTER pIniPrinter,
  662. IN SHARE_INFO_502 *pShareInfo502,
  663. OUT BOOL *pbSame
  664. )
  665. {
  666. DWORD rc = ERROR_SUCCESS;
  667. SHARE_INFO_2 *pShareInfoCompare = NULL;
  668. BOOL bPathEquivalent = FALSE;
  669. BOOL bSame = FALSE;
  670. DWORD ParmError;
  671. SplOutSem();
  672. //
  673. // Get the share info for the share, we should already have determined
  674. // that this share exists.
  675. //
  676. rc = pfnNetShareGetInfo(NULL, pShareInfo502->shi502_netname, 2, (LPBYTE *)&pShareInfoCompare);
  677. if (ERROR_SUCCESS == rc)
  678. {
  679. if (STYPE_PRINTQ == pShareInfoCompare->shi2_type)
  680. {
  681. //
  682. // Check to see whether the paths are the same, in the upgrade case, the
  683. // LocalSplOnly will be taken off, so, compare this too.
  684. //
  685. bSame = !_wcsicmp(pShareInfoCompare->shi2_path, pShareInfo502->shi502_path);
  686. //
  687. // If they are not the same, compare it to the name of the printer.
  688. //
  689. if (!bSame)
  690. {
  691. EnterSplSem();
  692. bSame = bPathEquivalent = !_wcsicmp(pIniPrinter->pName, pShareInfoCompare->shi2_path);
  693. LeaveSplSem();
  694. }
  695. }
  696. }
  697. *pbSame = bSame;
  698. if (ERROR_SUCCESS == rc && bSame)
  699. {
  700. //
  701. // If the paths are identical, we can just set the share info, otherwise
  702. // we have to delete and recreate the share.
  703. //
  704. if (!bPathEquivalent)
  705. {
  706. //
  707. // OK, they are the same, set the share info instead.
  708. //
  709. rc = (*pfnNetShareSetInfo)(NULL, pShareInfo502->shi502_netname, 502, pShareInfo502, &ParmError);
  710. }
  711. else
  712. {
  713. rc = (*pfnNetShareDel)(NULL, pShareInfo502->shi502_netname, 0);
  714. if (ERROR_SUCCESS == rc)
  715. {
  716. rc = (*pfnNetShareAdd)(NULL, 502, (LPBYTE)pShareInfo502, &ParmError);
  717. }
  718. }
  719. }
  720. if (pShareInfoCompare)
  721. {
  722. pfnNetApiBufferFree(pShareInfoCompare);
  723. }
  724. return rc;
  725. }