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.

2265 lines
66 KiB

  1. /*++
  2. Copyright (c) 1990 - 1995 Microsoft Corporation
  3. Module Name:
  4. setprn.c
  5. Abstract:
  6. This module provides all the public exported APIs relating to Printer
  7. management for the Local Print Providor
  8. SplSetPrinter
  9. Author:
  10. Dave Snipp (DaveSn) 15-Mar-1991
  11. Revision History:
  12. Muhunthan Sivapragasam (MuhuntS) 25-Aug-95
  13. -- support for level 4, and PRINTER_CONTROL_SET_STATUS.
  14. -- eliminate duplicate code
  15. Muhunthan Sivapragasam (MuhuntS) 18-Jun-1995 -- PeinterInfo5 changes
  16. Krishna Ganugapati (KrishnaG) 1-Jun-1994 -- rewrote these functions.
  17. SWilson - Added SetPrinter Level 7
  18. --*/
  19. #define NOMINMAX
  20. #include <precomp.h>
  21. #pragma hdrstop
  22. #include "clusspl.h"
  23. #define PRINTER_NO_CONTROL 0x00
  24. typedef enum {
  25. SECURITY_SUCCESS = 0,
  26. SECURITY_NOCHANGE = 1,
  27. SECURITY_FAIL = 2
  28. } PRINTER_SECURITY_STATUS;
  29. PRINTER_SECURITY_STATUS
  30. SetPrinterSecurity(
  31. SECURITY_INFORMATION SecurityInformation,
  32. PINIPRINTER pIniPrinter,
  33. PSECURITY_DESCRIPTOR pSecurityDescriptor
  34. );
  35. VOID
  36. RegClearKey(
  37. HKEY hKey,
  38. PINISPOOLER pIniSpooler
  39. );
  40. DWORD
  41. ValidatePrinterAttributes(
  42. DWORD SourceAttributes,
  43. DWORD OriginalAttributes,
  44. LPWSTR pDatatype,
  45. LPBOOL pbValid,
  46. BOOL bSettableOnly
  47. );
  48. BOOL
  49. ChangePrinterAttributes(
  50. DWORD dNewAttributes,
  51. DWORD dOldAttributes,
  52. PINIPRINTER pIniPrinter,
  53. PINISPOOLER pIniSpooler,
  54. LPWSTR pszNewShareName,
  55. BOOL bShareRecreate,
  56. BOOL bShareUpdate
  57. );
  58. BOOL
  59. NewPort(
  60. PKEYDATA pKeyData,
  61. PINIPRINTER pIniPrinter
  62. );
  63. BOOL
  64. SplSetPrinterExtraEx(
  65. HANDLE hPrinter,
  66. DWORD dwPrivateFlag
  67. )
  68. {
  69. BOOL ReturnValue = FALSE;
  70. PSPOOL pSpool = (PSPOOL)hPrinter;
  71. EnterSplSem();
  72. if (ValidateSpoolHandle(pSpool, PRINTER_HANDLE_SERVER)) {
  73. pSpool->pIniPrinter->dwPrivateFlag = dwPrivateFlag;
  74. ReturnValue = TRUE;
  75. }
  76. LeaveSplSem();
  77. return ReturnValue;
  78. }
  79. BOOL
  80. SplGetPrinterExtraEx(
  81. HANDLE hPrinter,
  82. LPDWORD pdwPrivateFlag
  83. )
  84. {
  85. BOOL ReturnValue = FALSE;
  86. PSPOOL pSpool = (PSPOOL)hPrinter;
  87. EnterSplSem();
  88. if ((pSpool != NULL) &&
  89. (pSpool != INVALID_HANDLE_VALUE) &&
  90. ValidateSpoolHandle(pSpool, PRINTER_HANDLE_SERVER) &&
  91. pdwPrivateFlag) {
  92. *pdwPrivateFlag = pSpool->pIniPrinter->dwPrivateFlag;
  93. ReturnValue = TRUE;
  94. }
  95. LeaveSplSem();
  96. return ReturnValue;
  97. }
  98. BOOL
  99. SplSetPrinterExtra(
  100. HANDLE hPrinter,
  101. LPBYTE pExtraData
  102. )
  103. {
  104. BOOL ReturnValue;
  105. PSPOOL pSpool = (PSPOOL)hPrinter;
  106. EnterSplSem();
  107. if (ValidateSpoolHandle(pSpool, PRINTER_HANDLE_SERVER)) {
  108. pSpool->pIniPrinter->pExtraData = pExtraData;
  109. UpdatePrinterIni( pSpool->pIniPrinter , UPDATE_CHANGEID );
  110. ReturnValue = TRUE;
  111. } else {
  112. ReturnValue = FALSE;
  113. }
  114. LeaveSplSem();
  115. return ReturnValue;
  116. }
  117. BOOL
  118. SplGetPrinterExtra(
  119. HANDLE hPrinter,
  120. PBYTE *ppExtraData
  121. )
  122. {
  123. PSPOOL pSpool = (PSPOOL)hPrinter;
  124. BOOL ReturnValue;
  125. if (ValidateSpoolHandle(pSpool, PRINTER_HANDLE_SERVER)) {
  126. *ppExtraData = pSpool->pIniPrinter->pExtraData;
  127. ReturnValue = TRUE;
  128. } else {
  129. ReturnValue = FALSE;
  130. }
  131. return ReturnValue;
  132. }
  133. BOOL
  134. ValidateLevelAndSecurityAccesses(
  135. PSPOOL pSpool,
  136. DWORD Level,
  137. LPBYTE pPrinterInfo,
  138. DWORD Command,
  139. PDWORD pdwAccessRequired,
  140. PDWORD pSecurityInformation
  141. )
  142. {
  143. DWORD AccessRequired = 0;
  144. DWORD SecurityInformation= 0;
  145. PSECURITY_DESCRIPTOR pSecurityDescriptor;
  146. //
  147. // Set pdwAccessRequired = 0 and
  148. // Set pSecurityInformation = 0;
  149. *pdwAccessRequired = 0;
  150. *pSecurityInformation = 0;
  151. switch (Level) {
  152. case 0:
  153. case 4:
  154. case 5:
  155. case 6:
  156. case 7:
  157. AccessRequired = PRINTER_ACCESS_ADMINISTER;
  158. break;
  159. case 2:
  160. pSecurityDescriptor =
  161. ((PPRINTER_INFO_2)pPrinterInfo)->pSecurityDescriptor;
  162. AccessRequired = PRINTER_ACCESS_ADMINISTER;
  163. if (GetSecurityInformation(pSecurityDescriptor,
  164. &SecurityInformation)) {
  165. AccessRequired |= GetPrivilegeRequired( SecurityInformation );
  166. } else {
  167. //
  168. // Bug 54918 - We should be returning the false on GetSecurityInformation
  169. // failing. The reason we're not doing it is because this will break
  170. // Printman. Printman should pass in Valid security descriptors for Level 2
  171. // Fix in Printman.
  172. //
  173. }
  174. break;
  175. case 3:
  176. pSecurityDescriptor =
  177. ((PPRINTER_INFO_3)pPrinterInfo)->pSecurityDescriptor;
  178. if (!pSecurityDescriptor) {
  179. SetLastError( ERROR_INVALID_PARAMETER );
  180. return FALSE;
  181. }
  182. if (GetSecurityInformation(pSecurityDescriptor,
  183. &SecurityInformation)) {
  184. AccessRequired |= GetPrivilegeRequired( SecurityInformation );
  185. } else {
  186. // LastError = GetLastError();
  187. return FALSE;
  188. }
  189. break;
  190. default:
  191. SetLastError(ERROR_INVALID_LEVEL);
  192. return FALSE;
  193. }
  194. if (!AccessGranted(SPOOLER_OBJECT_PRINTER,
  195. AccessRequired,
  196. pSpool) ) {
  197. SetLastError(ERROR_ACCESS_DENIED);
  198. return FALSE;
  199. }
  200. *pdwAccessRequired = AccessRequired;
  201. *pSecurityInformation = SecurityInformation;
  202. return TRUE;
  203. }
  204. PKEYDATA
  205. CreateAndValidatePortTokenList(
  206. LPWSTR pPortName,
  207. PINISPOOLER pIniSpooler
  208. )
  209. {
  210. PKEYDATA pKeyData = CreateTokenList(pPortName);
  211. if ( pKeyData ) {
  212. if ( !ValidatePortTokenList(pKeyData, pIniSpooler, FALSE, NULL) ) {
  213. FreePortTokenList(pKeyData);
  214. SetLastError(ERROR_UNKNOWN_PORT);
  215. pKeyData = NULL;
  216. }
  217. }
  218. return pKeyData;
  219. }
  220. BOOL
  221. NewPort(
  222. PKEYDATA pKeyData,
  223. PINIPRINTER pIniPrinter
  224. )
  225. {
  226. DWORD i, j;
  227. BOOL rc=TRUE;
  228. if (!pKeyData) {
  229. SetLastError(ERROR_UNKNOWN_PORT);
  230. return FALSE;
  231. }
  232. // Check if # of requested vs. existing ports differs
  233. if (pIniPrinter->cPorts != pKeyData->cTokens)
  234. return TRUE;
  235. // for each requested port see if printer already has it
  236. for (i = 0 ; i < pKeyData->cTokens ; ++i) {
  237. // see if requested port is already assigned to printer
  238. for (j = 0 ; j < pIniPrinter->cPorts &&
  239. wcscmp(pIniPrinter->ppIniPorts[j]->pName, ((PINIPORT)pKeyData->pTokens[i])->pName)
  240. ; ++j) {
  241. DBGMSG(DBG_TRACE,("NewPort (Existing vs. Requested): \"%ws\" ?= \"%ws\"\n",
  242. pIniPrinter->ppIniPorts[j]->pName, ((PINIPORT)pKeyData->pTokens[i])->pName));
  243. }
  244. if (j == pIniPrinter->cPorts) { // found new port, so return
  245. DBGMSG(DBG_TRACE,("NewPort FOUND: \"%ws\"\n", ((PINIPORT)pKeyData->pTokens[i])->pName));
  246. return TRUE;
  247. }
  248. }
  249. return FALSE;
  250. }
  251. VOID
  252. ChangePrinterName(
  253. LPWSTR pszNewName,
  254. PINIPRINTER pIniPrinter,
  255. PINISPOOLER pIniSpooler,
  256. LPDWORD pdwPrinterVector
  257. )
  258. /*++
  259. Routine Description:
  260. Changes printer name
  261. Arguments:
  262. pszNewName - New printer name allocated using AllocSplStr
  263. pIniPrinter - for the printer we changing name
  264. pIniSpooler - Spooler that owns printer
  265. pdwPrinterVector - pointer to notification vector
  266. Return Value:
  267. nothing
  268. --*/
  269. {
  270. LPWSTR pNewName, pOldName;
  271. //
  272. // Before deleting the printer entry make sure you copy
  273. // all information with respect to the printer to the registry
  274. // There could be several levels of keys.
  275. //
  276. CopyPrinterIni(pIniPrinter, pszNewName);
  277. DeletePrinterIni(pIniPrinter);
  278. pOldName = pIniPrinter->pName;
  279. pIniPrinter->pName = pszNewName;
  280. *pdwPrinterVector |= BIT(I_PRINTER_PRINTER_NAME);
  281. //
  282. // Delete the old entries in WIN.INI:
  283. //
  284. CheckAndUpdatePrinterRegAll(pIniSpooler,
  285. pOldName,
  286. NULL,
  287. UPDATE_REG_DELETE );
  288. FreeSplStr(pOldName);
  289. //
  290. // If printer is offline we need to write that info back with new name
  291. //
  292. if ( pIniPrinter->Attributes & PRINTER_ATTRIBUTE_WORK_OFFLINE )
  293. WritePrinterOnlineStatusInCurrentConfig(pIniPrinter);
  294. }
  295. BOOL
  296. SetLocalPrinterSTRESS(
  297. PINIPRINTER pIniPrinter,
  298. PPRINTER_INFO_STRESS pPrinterSTRESS
  299. )
  300. {
  301. if ( !pPrinterSTRESS ) {
  302. SetLastError(ERROR_INVALID_PARAMETER);
  303. return FALSE;
  304. }
  305. //
  306. // Allow the caller to update the counters.
  307. //
  308. pIniPrinter->cTotalJobs = pPrinterSTRESS->cTotalJobs;
  309. pIniPrinter->cTotalBytes.LowPart = pPrinterSTRESS->cTotalBytes;
  310. pIniPrinter->cTotalBytes.HighPart = pPrinterSTRESS->dwHighPartTotalBytes;
  311. pIniPrinter->MaxcRef = pPrinterSTRESS->MaxcRef;
  312. pIniPrinter->cTotalPagesPrinted = pPrinterSTRESS->cTotalPagesPrinted;
  313. pIniPrinter->cMaxSpooling = pPrinterSTRESS->cMaxSpooling;
  314. pIniPrinter->cErrorOutOfPaper = pPrinterSTRESS->cErrorOutOfPaper;
  315. pIniPrinter->cErrorNotReady = pPrinterSTRESS->cErrorNotReady;
  316. pIniPrinter->cJobError = pPrinterSTRESS->cJobError;
  317. pIniPrinter->dwLastError = pPrinterSTRESS->dwLastError;
  318. pIniPrinter->stUpTime = pPrinterSTRESS->stUpTime;
  319. pIniPrinter->pIniSpooler->cEnumerateNetworkPrinters =
  320. pPrinterSTRESS->cEnumerateNetworkPrinters;
  321. pIniPrinter->pIniSpooler->cAddNetPrinters =
  322. pPrinterSTRESS->cAddNetPrinters;
  323. UpdatePrinterIni( pIniPrinter, KEEP_CHANGEID );
  324. return TRUE;
  325. }
  326. BOOL
  327. SetPrinterStatus(
  328. PINIPRINTER pIniPrinter,
  329. DWORD Status
  330. )
  331. {
  332. DWORD OldStatus = pIniPrinter->Status;
  333. pIniPrinter->Status &= PRINTER_STATUS_PRIVATE;
  334. pIniPrinter->Status |= MapPrinterStatus(MAP_SETTABLE, Status);
  335. if ( PrinterStatusBad(OldStatus) &&
  336. !PrinterStatusBad(pIniPrinter->Status) ) {
  337. CHECK_SCHEDULER();
  338. }
  339. SetPrinterChange(pIniPrinter,
  340. NULL,
  341. NVPrinterStatus,
  342. PRINTER_CHANGE_SET_PRINTER,
  343. pIniPrinter->pIniSpooler);
  344. return TRUE;
  345. }
  346. BOOL
  347. SetLocalPrinter0(
  348. PINIPRINTER pIniPrinter,
  349. DWORD Command
  350. )
  351. {
  352. DWORD Change = PRINTER_CHANGE_SET_PRINTER;
  353. BOOL bReturn = TRUE;
  354. INCPRINTERREF( pIniPrinter );
  355. switch (Command) {
  356. case PRINTER_CONTROL_PURGE:
  357. //
  358. // PurgePrinter always returns TRUE now, still ..
  359. //
  360. if ( PurgePrinter(pIniPrinter) ) {
  361. SplLogEvent(pIniPrinter->pIniSpooler,
  362. LOG_WARNING,
  363. MSG_PRINTER_PURGED,
  364. TRUE,
  365. pIniPrinter->pName,
  366. NULL );
  367. Change |= PRINTER_CHANGE_DELETE_JOB;
  368. } else {
  369. bReturn = FALSE;
  370. }
  371. break;
  372. case PRINTER_CONTROL_RESUME:
  373. pIniPrinter->Status &= ~PRINTER_PAUSED;
  374. CHECK_SCHEDULER();
  375. UpdatePrinterIni( pIniPrinter, KEEP_CHANGEID );
  376. SplLogEvent(pIniPrinter->pIniSpooler,
  377. LOG_WARNING,
  378. MSG_PRINTER_UNPAUSED,
  379. TRUE,
  380. pIniPrinter->pName,
  381. NULL );
  382. //
  383. // WMI Trace Events.
  384. //
  385. {
  386. //
  387. // Wmi only knows about jobs, so each job needs to be resumed
  388. // separately.
  389. //
  390. PINIJOB pIniJob = pIniPrinter->pIniFirstJob;
  391. while (pIniJob)
  392. {
  393. if ( !((pIniJob->Status & JOB_DESPOOLING) ||
  394. (pIniJob->Status & JOB_PRINTING) ||
  395. (pIniJob->Status & JOB_PRINTED) ||
  396. (pIniJob->Status & JOB_ABANDON)) )
  397. {
  398. LogWmiTraceEvent(pIniJob->JobId,
  399. EVENT_TRACE_TYPE_SPL_RESUME, NULL);
  400. }
  401. pIniJob = pIniJob->pIniNextJob;
  402. }
  403. }
  404. break;
  405. case PRINTER_CONTROL_PAUSE:
  406. //
  407. // You can't pause a fax printer. This locks up the fax server. The
  408. // fax service also has its own concept of paused.
  409. //
  410. if (!(pIniPrinter->Attributes & PRINTER_ATTRIBUTE_FAX)) {
  411. pIniPrinter->Status |= PRINTER_PAUSED;
  412. UpdatePrinterIni( pIniPrinter, KEEP_CHANGEID );
  413. SplLogEvent(pIniPrinter->pIniSpooler,
  414. LOG_WARNING,
  415. MSG_PRINTER_PAUSED,
  416. TRUE,
  417. pIniPrinter->pName,
  418. NULL);
  419. //
  420. // WMI Trace Events
  421. //
  422. {
  423. //
  424. // Wmi only knows about jobs, so each job needs to be paused
  425. // separately.
  426. //
  427. PINIJOB pIniJob = pIniPrinter->pIniFirstJob;
  428. while (pIniJob)
  429. {
  430. //
  431. // HANDLE PRINTING DIRECT ???
  432. // I don't believe pausing a printer can stop a job already
  433. // being sent to the printer.
  434. //
  435. if ( !((pIniJob->Status & JOB_DESPOOLING) ||
  436. (pIniJob->Status & JOB_PRINTING) ||
  437. (pIniJob->Status & JOB_PRINTED) ||
  438. (pIniJob->Status & JOB_ABANDON)) )
  439. {
  440. LogWmiTraceEvent(pIniJob->JobId,
  441. EVENT_TRACE_TYPE_SPL_PAUSE,
  442. NULL);
  443. }
  444. pIniJob = pIniJob->pIniNextJob;
  445. }
  446. }
  447. }
  448. else {
  449. bReturn = FALSE;
  450. SetLastError(ERROR_INVALID_PARAMETER);
  451. }
  452. break;
  453. default:
  454. SetLastError(ERROR_INVALID_PRINTER_COMMAND);
  455. bReturn = FALSE;
  456. break;
  457. }
  458. DECPRINTERREF( pIniPrinter );
  459. if (bReturn) {
  460. SetPrinterChange(pIniPrinter,
  461. NULL,
  462. (Command == PRINTER_CONTROL_PURGE) ? NVPurge
  463. : NVPrinterStatus,
  464. Change,
  465. pIniPrinter->pIniSpooler);
  466. }
  467. return bReturn;
  468. }
  469. BOOL
  470. ValidateSetPrinter2(
  471. PINIPRINTER pIniPrinter,
  472. PINIPRINTER pTempIniPrinter,
  473. PPRINTER_INFO_2 pPrinterInfo2
  474. )
  475. /*++
  476. Routine Description:
  477. Validates and builds request info about a SetPrinter info call for
  478. Printer information that could be changed only for level2.
  479. Arguments:
  480. pIniPrinter - PINIPRINTER of the printer handle passed in
  481. pTempIniPrinter - this structure is used to gather info about all
  482. parameters being changed
  483. pPrinterInfo2 - the PrinterInfo2 structure being passed in
  484. Return Value:
  485. TRUE: If all the validation is succesful
  486. FALSE: If validation of one or more request fails
  487. On succesful return fields which need to be changed will be set in
  488. pTempIniPrinter. Cleanup of this structure will be done later.
  489. --*/
  490. {
  491. BOOL bFail = FALSE;
  492. DWORD LastError = ERROR_SUCCESS;
  493. PINIVERSION pIniVersion = NULL;
  494. PINIENVIRONMENT pIniEnvironment = NULL;
  495. BOOL bSuccess = FALSE;
  496. // Servername can't change
  497. // Printername handled for level 2, 4, 5
  498. // Sharenname length validation
  499. if ( pPrinterInfo2->pShareName && wcslen(pPrinterInfo2->pShareName) > PATHLEN-1 ){
  500. bFail = TRUE;
  501. LastError = ERROR_INVALID_PARAMETER;
  502. }
  503. // Share Name (validation later if required)
  504. AllocOrUpdateString(&pTempIniPrinter->pShareName,
  505. pPrinterInfo2->pShareName,
  506. pIniPrinter->pShareName,
  507. TRUE,
  508. &bFail);
  509. if ( bFail )
  510. goto Cleanup;
  511. // Port Name for level 2, 5
  512. // DriverName
  513. bSuccess = FindLocalDriverAndVersion(pIniPrinter->pIniSpooler,
  514. pPrinterInfo2->pDriverName,
  515. &pTempIniPrinter->pIniDriver,
  516. &pIniVersion);
  517. if ( !bSuccess ) {
  518. LastError = ERROR_UNKNOWN_PRINTER_DRIVER;
  519. goto Cleanup;
  520. }
  521. pIniEnvironment = GetLocalArchEnv(pIniPrinter->pIniSpooler);
  522. //
  523. // If we have a queue with a KMPD, then we need to let the user manage it,
  524. // even if the policy for blocking KMPD is enabled. However, if the caller
  525. // wants to change the printer driver to a KMPD, then we do not allow that
  526. //
  527. if (pTempIniPrinter->pIniDriver != pIniPrinter->pIniDriver)
  528. {
  529. INCDRIVERREF(pTempIniPrinter->pIniDriver);
  530. if (KMPrintersAreBlocked() &&
  531. IniDriverIsKMPD(pIniPrinter->pIniSpooler,
  532. pIniEnvironment,
  533. pIniVersion,
  534. pTempIniPrinter->pIniDriver)) {
  535. SplLogEvent( pIniPrinter->pIniSpooler,
  536. LOG_ERROR,
  537. MSG_KM_PRINTERS_BLOCKED,
  538. TRUE,
  539. pIniPrinter->pName,
  540. NULL );
  541. LastError = ERROR_KM_DRIVER_BLOCKED;
  542. goto Cleanup;
  543. }
  544. }
  545. // Comment length validation
  546. if ( pPrinterInfo2->pComment && wcslen(pPrinterInfo2->pComment) > PATHLEN-1 ){
  547. bFail = TRUE;
  548. LastError = ERROR_INVALID_PARAMETER;
  549. }
  550. // Comment
  551. AllocOrUpdateString(&pTempIniPrinter->pComment,
  552. pPrinterInfo2->pComment,
  553. pIniPrinter->pComment,
  554. TRUE,
  555. &bFail);
  556. // Location length validation
  557. if ( pPrinterInfo2->pLocation && wcslen(pPrinterInfo2->pLocation) > MAX_PATH-1 ){
  558. bFail = TRUE;
  559. LastError = ERROR_INVALID_PARAMETER;
  560. }
  561. // Location
  562. AllocOrUpdateString(&pTempIniPrinter->pLocation,
  563. pPrinterInfo2->pLocation,
  564. pIniPrinter->pLocation,
  565. TRUE,
  566. &bFail);
  567. // DevMode at the end
  568. // SepFile length validation
  569. if( !CheckSepFile( pPrinterInfo2->pSepFile )) {
  570. bFail = TRUE;
  571. LastError = ERROR_INVALID_SEPARATOR_FILE;
  572. }
  573. // SepFile
  574. AllocOrUpdateString(&pTempIniPrinter->pSepFile,
  575. pPrinterInfo2->pSepFile,
  576. pIniPrinter->pSepFile,
  577. TRUE,
  578. &bFail);
  579. if ( bFail )
  580. goto Cleanup;
  581. if ( pIniPrinter->pSepFile != pTempIniPrinter->pSepFile &&
  582. !CheckSepFile(pPrinterInfo2->pSepFile) ) {
  583. LastError = ERROR_INVALID_SEPARATOR_FILE;
  584. goto Cleanup;
  585. }
  586. // Print Processor
  587. pTempIniPrinter->pIniPrintProc = FindPrintProc(
  588. pPrinterInfo2->pPrintProcessor,
  589. pIniEnvironment );
  590. if ( !pTempIniPrinter->pIniPrintProc ) {
  591. LastError = ERROR_UNKNOWN_PRINTPROCESSOR;
  592. goto Cleanup;
  593. }
  594. if ( pTempIniPrinter->pIniPrintProc != pIniPrinter->pIniPrintProc )
  595. pTempIniPrinter->pIniPrintProc->cRef++;
  596. // Datatype
  597. if ( !pPrinterInfo2->pDatatype || wcslen(pPrinterInfo2->pDatatype) > MAX_PATH-1) {
  598. LastError = ERROR_INVALID_DATATYPE;
  599. goto Cleanup; // Ok to fail ???
  600. } else {
  601. AllocOrUpdateString(&pTempIniPrinter->pDatatype,
  602. pPrinterInfo2->pDatatype,
  603. pIniPrinter->pDatatype,
  604. TRUE,
  605. &bFail);
  606. }
  607. // Parameters length validation
  608. if (pPrinterInfo2->pParameters && wcslen(pPrinterInfo2->pParameters) > MAX_PATH-1){
  609. bFail = TRUE;
  610. LastError = ERROR_INVALID_PARAMETER;
  611. }
  612. // Parameters
  613. AllocOrUpdateString(&pTempIniPrinter->pParameters,
  614. pPrinterInfo2->pParameters,
  615. pIniPrinter->pParameters,
  616. TRUE,
  617. &bFail);
  618. if ( bFail )
  619. goto Cleanup;
  620. // SecurityDescriptor for level 2, 3
  621. // Attributes for level 2, 4, 5
  622. // Priority
  623. pTempIniPrinter->Priority = pPrinterInfo2->Priority;
  624. if ( pTempIniPrinter->Priority != pIniPrinter->Priority &&
  625. pTempIniPrinter->Priority != NO_PRIORITY &&
  626. ( pTempIniPrinter->Priority > MAX_PRIORITY ||
  627. pTempIniPrinter->Priority < MIN_PRIORITY ) ) {
  628. LastError = ERROR_INVALID_PRIORITY;
  629. goto Cleanup;
  630. }
  631. // Default Priority
  632. pTempIniPrinter->DefaultPriority = pPrinterInfo2->DefaultPriority;
  633. if ( pTempIniPrinter->DefaultPriority != pIniPrinter->DefaultPriority &&
  634. pTempIniPrinter->DefaultPriority != NO_PRIORITY &&
  635. ( pTempIniPrinter->DefaultPriority > MAX_PRIORITY ||
  636. pTempIniPrinter->DefaultPriority < MIN_PRIORITY ) ) {
  637. LastError = ERROR_INVALID_PRIORITY;
  638. goto Cleanup;
  639. }
  640. // Start time
  641. pTempIniPrinter->StartTime = pPrinterInfo2->StartTime;
  642. if ( pTempIniPrinter->StartTime != pIniPrinter->StartTime &&
  643. pTempIniPrinter->StartTime >= ONEDAY ) {
  644. LastError = ERROR_INVALID_TIME;
  645. goto Cleanup;
  646. }
  647. // Until time
  648. pTempIniPrinter->UntilTime = pPrinterInfo2->UntilTime;
  649. if ( pTempIniPrinter->UntilTime != pIniPrinter->UntilTime &&
  650. pTempIniPrinter->StartTime >= ONEDAY ) {
  651. LastError = ERROR_INVALID_TIME;
  652. goto Cleanup;
  653. }
  654. // Status for level 0, 2
  655. // Status can't chg
  656. // AveragePPM can't chg
  657. Cleanup:
  658. if ( LastError ) {
  659. SetLastError(LastError);
  660. return FALSE;
  661. }
  662. if ( bFail )
  663. return FALSE;
  664. return TRUE;
  665. }
  666. VOID
  667. ProcessSetPrinter2(
  668. PINIPRINTER pIniPrinter,
  669. PINIPRINTER pTempIniPrinter,
  670. PPRINTER_INFO_2 pPrinterInfo2,
  671. LPDWORD pdwPrinterVector,
  672. PDEVMODE pDevMode
  673. )
  674. /*++
  675. Routine Description:
  676. Process SetPrinter for level 2. Only fields which can be changed ONLY
  677. by level 2 will be processed here. That is: All the fields built by
  678. ValidateSetPrinter2.
  679. Arguments:
  680. pIniPrinter - PINIPRINTER of the printer handle passed in
  681. pTempIniPrinter - this structure is has all the fields which needs to
  682. be set. Other fields will be the same as the previous
  683. pPrinterInfo2 - the PrinterInfo2 structure being passed in
  684. pdwPrinterVector - Notification Info
  685. pDevMode - New dev mode to be set
  686. Return Value:
  687. nothing
  688. --*/
  689. {
  690. HANDLE hToken;
  691. PINISPOOLER pIniSpooler = pIniPrinter->pIniSpooler;
  692. HKEY hKey = NULL;
  693. DWORD dwResult;
  694. // Sharename
  695. if ( pTempIniPrinter->pShareName != pIniPrinter->pShareName ) {
  696. FreeSplStr(pIniPrinter->pShareName);
  697. pIniPrinter->pShareName = pTempIniPrinter->pShareName;
  698. *pdwPrinterVector |= BIT(I_PRINTER_SHARE_NAME);
  699. }
  700. // Driver
  701. if ( pTempIniPrinter->pIniDriver != pIniPrinter->pIniDriver) {
  702. DECDRIVERREF(pIniPrinter->pIniDriver);
  703. if (pIniPrinter->pIniSpooler->SpoolerFlags & SPL_PRINTER_DRIVER_EVENT)
  704. {
  705. hToken = RevertToPrinterSelf();
  706. dwResult = OpenPrinterKey(pIniPrinter, KEY_READ | KEY_WRITE, &hKey, szPrinterData, TRUE);
  707. if (dwResult == ERROR_SUCCESS) {
  708. DeleteSubkeys( hKey, pIniSpooler );
  709. RegClearKey( hKey, pIniSpooler );
  710. SplRegCloseKey(hKey, pIniPrinter->pIniSpooler);
  711. }
  712. if (hToken)
  713. ImpersonatePrinterClient(hToken);
  714. }
  715. pIniPrinter->pIniDriver = pTempIniPrinter->pIniDriver;
  716. *pdwPrinterVector |= BIT(I_PRINTER_DRIVER_NAME);
  717. }
  718. // Comment
  719. if ( pTempIniPrinter->pComment != pIniPrinter->pComment ) {
  720. FreeSplStr(pIniPrinter->pComment);
  721. pIniPrinter->pComment = pTempIniPrinter->pComment;
  722. *pdwPrinterVector |= BIT(I_PRINTER_COMMENT);
  723. }
  724. // Location
  725. if ( pTempIniPrinter->pLocation != pIniPrinter->pLocation ) {
  726. FreeSplStr(pIniPrinter->pLocation);
  727. pIniPrinter->pLocation = pTempIniPrinter->pLocation;
  728. *pdwPrinterVector |= BIT(I_PRINTER_LOCATION);
  729. }
  730. // DevMode at the end
  731. if ( CopyPrinterDevModeToIniPrinter(pIniPrinter,
  732. pDevMode) ) {
  733. *pdwPrinterVector |= BIT(I_PRINTER_DEVMODE);
  734. }
  735. // SepFile
  736. if ( pTempIniPrinter->pSepFile != pIniPrinter->pSepFile ) {
  737. FreeSplStr(pIniPrinter->pSepFile);
  738. pIniPrinter->pSepFile = pTempIniPrinter->pSepFile;
  739. *pdwPrinterVector |= BIT(I_PRINTER_SEPFILE);
  740. }
  741. // PrintProcessor
  742. if ( pIniPrinter->pIniPrintProc != pTempIniPrinter->pIniPrintProc) {
  743. pIniPrinter->pIniPrintProc->cRef--;
  744. pIniPrinter->pIniPrintProc = pTempIniPrinter->pIniPrintProc;
  745. *pdwPrinterVector |= BIT(I_PRINTER_PRINT_PROCESSOR);
  746. }
  747. // Datatype
  748. if ( pIniPrinter->pDatatype != pTempIniPrinter->pDatatype ) {
  749. FreeSplStr(pIniPrinter->pDatatype);
  750. pIniPrinter->pDatatype = pTempIniPrinter->pDatatype;
  751. *pdwPrinterVector |= BIT(I_PRINTER_DATATYPE);
  752. }
  753. // Parameters
  754. if ( pIniPrinter->pParameters != pTempIniPrinter->pParameters ) {
  755. FreeSplStr(pIniPrinter->pParameters);
  756. pIniPrinter->pParameters = pTempIniPrinter->pParameters;
  757. *pdwPrinterVector |= BIT(I_PRINTER_PARAMETERS);
  758. }
  759. // Priority
  760. if ( pTempIniPrinter->Priority != pIniPrinter->Priority ) {
  761. pIniPrinter->Priority = pTempIniPrinter->Priority;
  762. *pdwPrinterVector |= BIT(I_PRINTER_PRIORITY);
  763. }
  764. // Default Priority
  765. if ( pTempIniPrinter->DefaultPriority != pIniPrinter->DefaultPriority ) {
  766. pIniPrinter->DefaultPriority = pTempIniPrinter->DefaultPriority;
  767. *pdwPrinterVector |= BIT(I_PRINTER_DEFAULT_PRIORITY);
  768. }
  769. // Start time
  770. if ( pTempIniPrinter->StartTime != pIniPrinter->StartTime ) {
  771. pIniPrinter->StartTime = pTempIniPrinter->StartTime;
  772. *pdwPrinterVector |= BIT(I_PRINTER_START_TIME);
  773. }
  774. // Until time
  775. if ( pTempIniPrinter->UntilTime != pIniPrinter->UntilTime ) {
  776. pIniPrinter->UntilTime = pTempIniPrinter->UntilTime;
  777. *pdwPrinterVector |= BIT(I_PRINTER_UNTIL_TIME);
  778. }
  779. }
  780. VOID
  781. CleanupSetPrinter(
  782. PINIPRINTER pIniPrinter,
  783. PINIPRINTER pTempIniPrinter,
  784. PKEYDATA pKeyData,
  785. DWORD Level,
  786. BOOL bReturnValue
  787. )
  788. /*++
  789. Routine Description:
  790. This routine is called at the end of SplSetPrinter call to free up all
  791. the allocations done to process it which are not needed.
  792. At the beginning of a SetPrinter we make an identical copy of the
  793. pIniPrinter in pTempIniPrinter and collect all arguments in there.
  794. Now if the call is failing each of the arguments collected in there
  795. need to be freed.
  796. Arguments:
  797. pIniPrinter - PINIPRINTER of the printer handle passed in
  798. pTempIniPrinter - this structure is has all the fields which needs to
  799. be freed. Any field different than pIniPrinter was
  800. built part of processing the call and needs to be freed.
  801. pPrinterInfo2 - built for port info
  802. bReturnValue - return value of SetPrinter
  803. Return Value:
  804. nothing
  805. --*/
  806. {
  807. //
  808. // We adjust INIPORT, INIDRIVER refcounts. So should be inside the spl sem
  809. //
  810. SplInSem();
  811. FreePortTokenList(pKeyData);
  812. if ( pTempIniPrinter ) {
  813. if ( !bReturnValue && Level == 2 ) {
  814. if ( pTempIniPrinter->pShareName != pIniPrinter->pShareName )
  815. FreeSplStr(pTempIniPrinter->pShareName);
  816. if ( pTempIniPrinter->pComment != pIniPrinter->pComment )
  817. FreeSplStr(pTempIniPrinter->pComment);
  818. if ( pTempIniPrinter->pLocation != pIniPrinter->pLocation )
  819. FreeSplStr(pTempIniPrinter->pLocation);
  820. if ( pTempIniPrinter->pSepFile != pIniPrinter->pSepFile )
  821. FreeSplStr(pTempIniPrinter->pSepFile);
  822. if ( pTempIniPrinter->pDatatype != pIniPrinter->pDatatype )
  823. FreeSplStr(pTempIniPrinter->pDatatype);
  824. if ( pTempIniPrinter->pParameters != pIniPrinter->pParameters )
  825. FreeSplStr(pTempIniPrinter->pParameters);
  826. if ( ( pTempIniPrinter->pIniDriver != NULL ) &&
  827. ( pTempIniPrinter->pIniDriver != pIniPrinter->pIniDriver )) {
  828. DECDRIVERREF(pTempIniPrinter->pIniDriver);
  829. }
  830. if ( ( pTempIniPrinter->pIniPrintProc != NULL ) &&
  831. ( pTempIniPrinter->pIniPrintProc != pIniPrinter->pIniPrintProc )) {
  832. pTempIniPrinter->pIniPrintProc->cRef--;
  833. }
  834. }
  835. FreeSplMem(pTempIniPrinter);
  836. }
  837. }
  838. BOOL
  839. ValidateAndBuildSetPrinterRequest(
  840. PINIPRINTER pIniPrinter,
  841. PINIPRINTER pTempIniPrinter,
  842. LPBYTE pPrinterInfo,
  843. DWORD Level,
  844. SECURITY_INFORMATION SecurityInformation,
  845. LPBOOL pbSecurityChg,
  846. LPBOOL pbNameChg,
  847. LPBOOL pbAttributeChg,
  848. LPWSTR *ppszNewPrinterName,
  849. PKEYDATA *ppKeyData
  850. )
  851. /*++
  852. Routine Description:
  853. This routine is called to validate a SetPrinter request. We try to as
  854. much vaidation as possible at the beginning to see the changes are
  855. possible. The routine will collect all changes requested in the
  856. pTempIniPrinter structure.
  857. Arguments:
  858. pIniPrinter - PINIPRINTER of the printer handle passed in
  859. pTempIniPrinter - this structure will be used to collect all the
  860. changes requested
  861. pPrinterInfo - PrinterInfo_N structure passed in
  862. Level - Level of PrinterInfo_N
  863. SecurityInformation - security information
  864. pbSecurityChg - this will be set if a security change is requested
  865. pbNameChg - this will be set if a name change is requested
  866. pbAttributeChg - this will be set if a attribute change is requested
  867. ppszNewPrinterName - *ppszNewPrinterName will give the new printer name
  868. to be set on a name change
  869. ppKeyData - *ppKeyData will give the Port token info for a level 2 or 5
  870. call
  871. Return Value:
  872. TRUE - if all the validations succeed
  873. FALSE - a validation fails
  874. --*/
  875. {
  876. PPRINTER_INFO_2 pPrinterInfo2 = (PPRINTER_INFO_2)pPrinterInfo;
  877. PPRINTER_INFO_3 pPrinterInfo3 = (PPRINTER_INFO_3)pPrinterInfo;
  878. PPRINTER_INFO_4 pPrinterInfo4 = (PPRINTER_INFO_4)pPrinterInfo;
  879. PPRINTER_INFO_5 pPrinterInfo5 = (PPRINTER_INFO_5)pPrinterInfo;
  880. LPWSTR pPortName;
  881. DWORD dwLastError;
  882. BOOL bValid = TRUE;
  883. switch (Level) {
  884. case 2:
  885. pTempIniPrinter->pSecurityDescriptor =
  886. pPrinterInfo2->pSecurityDescriptor;
  887. if ( !ValidateSetPrinter2(pIniPrinter, pTempIniPrinter, pPrinterInfo2) )
  888. return FALSE;
  889. pTempIniPrinter->pName = pPrinterInfo2->pPrinterName;
  890. pPortName = pPrinterInfo2->pPortName;
  891. if ( !pTempIniPrinter->pIniDriver->pIniLangMonitor )
  892. pPrinterInfo2->Attributes &= ~PRINTER_ATTRIBUTE_ENABLE_BIDI;
  893. if ( pIniPrinter->pIniDriver != pTempIniPrinter->pIniDriver ) {
  894. pPrinterInfo2->Attributes &= ~PRINTER_ATTRIBUTE_ENABLE_BIDI;
  895. if ( pTempIniPrinter->pIniDriver->pIniLangMonitor )
  896. pPrinterInfo2->Attributes |= PRINTER_ATTRIBUTE_ENABLE_BIDI;
  897. }
  898. pTempIniPrinter->Attributes =
  899. ValidatePrinterAttributes(pPrinterInfo2->Attributes,
  900. pIniPrinter->Attributes,
  901. pPrinterInfo2->pDatatype,
  902. &bValid,
  903. TRUE);
  904. if (!bValid) {
  905. return FALSE;
  906. }
  907. *pbAttributeChg = pTempIniPrinter->Attributes != pIniPrinter->Attributes;
  908. break;
  909. case 3:
  910. pTempIniPrinter->pSecurityDescriptor = pPrinterInfo3->pSecurityDescriptor;
  911. if ( !SecurityInformation || !pTempIniPrinter->pSecurityDescriptor ) {
  912. SetLastError(ERROR_INVALID_PARAMETER);
  913. return FALSE;
  914. }
  915. break;
  916. case 4:
  917. pTempIniPrinter->pName = pPrinterInfo4->pPrinterName;
  918. if ( !pIniPrinter->pIniDriver->pIniLangMonitor )
  919. pPrinterInfo4->Attributes &= ~PRINTER_ATTRIBUTE_ENABLE_BIDI;
  920. pTempIniPrinter->Attributes =
  921. ValidatePrinterAttributes(pPrinterInfo4->Attributes,
  922. pIniPrinter->Attributes,
  923. pIniPrinter->pDatatype,
  924. &bValid,
  925. TRUE);
  926. if (!bValid) {
  927. return FALSE;
  928. }
  929. *pbAttributeChg = pTempIniPrinter->Attributes != pIniPrinter->Attributes;
  930. break;
  931. case 5:
  932. pTempIniPrinter->pName = pPrinterInfo5->pPrinterName;
  933. pPortName = pPrinterInfo5->pPortName;
  934. if ( !pIniPrinter->pIniDriver->pIniLangMonitor )
  935. pPrinterInfo5->Attributes &= ~PRINTER_ATTRIBUTE_ENABLE_BIDI;
  936. pTempIniPrinter->Attributes =
  937. ValidatePrinterAttributes(pPrinterInfo5->Attributes,
  938. pIniPrinter->Attributes,
  939. pIniPrinter->pDatatype,
  940. &bValid,
  941. TRUE);
  942. if (!bValid) {
  943. return FALSE;
  944. }
  945. *pbAttributeChg = pTempIniPrinter->Attributes != pIniPrinter->Attributes;
  946. //
  947. // Validate timeout?
  948. //
  949. pTempIniPrinter->dnsTimeout = pPrinterInfo5->DeviceNotSelectedTimeout;
  950. pTempIniPrinter->txTimeout = pPrinterInfo5->TransmissionRetryTimeout;
  951. break;
  952. default:
  953. SetLastError(ERROR_INVALID_LEVEL);
  954. return FALSE;
  955. }
  956. //
  957. // Validate share name if the shared bit is getting set or share name
  958. // is being changed
  959. //
  960. if ( (pTempIniPrinter->Attributes & PRINTER_ATTRIBUTE_SHARED) &&
  961. ( !(pIniPrinter->Attributes & PRINTER_ATTRIBUTE_SHARED) ||
  962. pTempIniPrinter->pShareName != pIniPrinter->pShareName) ) {
  963. if (gRemoteRPCEndPointPolicy == RpcEndPointPolicyDisabled)
  964. {
  965. SetLastError(ERROR_REMOTE_PRINT_CONNECTIONS_BLOCKED);
  966. return FALSE;
  967. }
  968. dwLastError = ValidatePrinterShareName(pTempIniPrinter->pShareName,
  969. pIniPrinter->pIniSpooler,
  970. pIniPrinter);
  971. if ( dwLastError != ERROR_SUCCESS ) {
  972. SetLastError(dwLastError);
  973. return FALSE;
  974. }
  975. }
  976. //
  977. // Is there a security change?
  978. //
  979. if ( SecurityInformation && (Level == 2 || Level == 3) ) {
  980. DWORD dwSize;
  981. dwSize = GetSecurityDescriptorLength(pIniPrinter->pSecurityDescriptor);
  982. if ( dwSize !=
  983. GetSecurityDescriptorLength(pTempIniPrinter->pSecurityDescriptor) ||
  984. memcmp(pTempIniPrinter->pSecurityDescriptor,
  985. pIniPrinter->pSecurityDescriptor,
  986. dwSize) ) {
  987. *pbSecurityChg = TRUE;
  988. }
  989. }
  990. //
  991. // Is there a name change?
  992. //
  993. if ( Level == 2 || Level == 4 || Level == 5 ) {
  994. DWORD LastError;
  995. if ( !pTempIniPrinter->pName || !*pTempIniPrinter->pName ) {
  996. SetLastError(ERROR_INVALID_PARAMETER);
  997. return FALSE;
  998. }
  999. //
  1000. // Validate name if a change is requested
  1001. //
  1002. if ( lstrcmpi(pTempIniPrinter->pName, pIniPrinter->pName) ) {
  1003. LastError = ValidatePrinterName(pTempIniPrinter->pName,
  1004. pIniPrinter->pIniSpooler,
  1005. pIniPrinter,
  1006. ppszNewPrinterName);
  1007. if ( LastError != ERROR_SUCCESS ) {
  1008. *ppszNewPrinterName = NULL;
  1009. SetLastError(LastError);
  1010. return FALSE;
  1011. }
  1012. //
  1013. // Check if printer name really changed for remote calls
  1014. //
  1015. if ( lstrcmpi(*ppszNewPrinterName, pIniPrinter->pName) ) {
  1016. *ppszNewPrinterName = AllocSplStr(*ppszNewPrinterName);
  1017. if ( !*ppszNewPrinterName )
  1018. return FALSE;
  1019. *pbNameChg = TRUE;
  1020. } else {
  1021. *ppszNewPrinterName = NULL;
  1022. }
  1023. }
  1024. //
  1025. // Validate attributes if a change is requested
  1026. // Don't allow a change from queued to direct or vice versa
  1027. // if there are already jobs on the printer.
  1028. //
  1029. if ( pIniPrinter->cJobs > 0 ) {
  1030. if ( (pTempIniPrinter->Attributes & PRINTER_ATTRIBUTE_DIRECT) !=
  1031. (pIniPrinter->Attributes & PRINTER_ATTRIBUTE_DIRECT) ) {
  1032. SetLastError(ERROR_PRINTER_HAS_JOBS_QUEUED);
  1033. return FALSE;
  1034. }
  1035. }
  1036. }
  1037. if ( Level == 2 || Level == 5 ) {
  1038. if ( !pPortName || !*pPortName ) {
  1039. SetLastError(ERROR_UNKNOWN_PORT);
  1040. return FALSE;
  1041. }
  1042. *ppKeyData = CreateAndValidatePortTokenList(pPortName,
  1043. pIniPrinter->pIniSpooler);
  1044. if ( !*ppKeyData )
  1045. return FALSE;
  1046. }
  1047. return TRUE;
  1048. }
  1049. BOOL
  1050. SplSetPrinter(
  1051. HANDLE hPrinter,
  1052. DWORD Level,
  1053. LPBYTE pPrinterInfo,
  1054. DWORD Command
  1055. )
  1056. {
  1057. PSPOOL pSpool = (PSPOOL)hPrinter;
  1058. DWORD i, LastError = ERROR_SUCCESS;
  1059. DWORD AccessRequired = 0;
  1060. PINIPRINTER pIniPrinter = pSpool->pIniPrinter, pTempIniPrinter = NULL;
  1061. PINISPOOLER pIniSpooler;
  1062. BOOL bReturn = TRUE;
  1063. DWORD dwResult;
  1064. BOOL bShareUpdate;
  1065. BOOL bShareRecreate;
  1066. DWORD dwPrinterVector = 0;
  1067. NOTIFYVECTOR NotifyVector;
  1068. BOOL bUpdateDsSpoolerKey = FALSE;
  1069. BOOL bNewPort;
  1070. BOOL bDataChanged = FALSE;
  1071. DWORD OldAttributes = 0;
  1072. DWORD dwPrnEvntError = ERROR_SUCCESS;
  1073. PPRINTER_INFO_2 pPrinterInfo2 = (PPRINTER_INFO_2)pPrinterInfo;
  1074. PPRINTER_INFO_3 pPrinterInfo3 = (PPRINTER_INFO_3)pPrinterInfo;
  1075. PPRINTER_INFO_4 pPrinterInfo4 = (PPRINTER_INFO_4)pPrinterInfo;
  1076. PPRINTER_INFO_5 pPrinterInfo5 = (PPRINTER_INFO_5)pPrinterInfo;
  1077. PPRINTER_INFO_7 pPrinterInfo7 = (PPRINTER_INFO_7)pPrinterInfo;
  1078. PRINTER_INFO_7 PrinterInfo7;
  1079. BOOL bSecurityChg, bNameChg, bAttributeChg;
  1080. LPWSTR pszNewPrinterName = NULL, pszOldPrinterName = NULL;
  1081. PINIJOB pIniJob;
  1082. PKEYDATA pKeyData = NULL;
  1083. PDEVMODE pDevMode = NULL;
  1084. PINIDRIVER pIniDriver;
  1085. PINIPRINTPROC pIniPrintProc;
  1086. SECURITY_INFORMATION SecurityInformation;
  1087. ZERONV(NotifyVector);
  1088. bSecurityChg = bNameChg = bAttributeChg = FALSE;
  1089. bShareUpdate = bShareRecreate = FALSE;
  1090. //
  1091. // If level != 0 info struct should be non-null, and command 0
  1092. //
  1093. if ( Level && Command ) {
  1094. SetLastError(ERROR_INVALID_PRINTER_COMMAND);
  1095. return FALSE;
  1096. }
  1097. if ( Level && !pPrinterInfo ) {
  1098. SetLastError(ERROR_INVALID_PARAMETER);
  1099. return FALSE;
  1100. }
  1101. EnterSplSem();
  1102. if (!ValidateSpoolHandle(pSpool, PRINTER_HANDLE_SERVER )) {
  1103. bReturn = FALSE;
  1104. goto Cleanup;
  1105. }
  1106. //
  1107. // If it is a remote call get default devmode from driver and then update it
  1108. //
  1109. if ( Level == 2 ) {
  1110. pDevMode = pPrinterInfo2->pDevMode;
  1111. if ( pDevMode && (pSpool->TypeofHandle & PRINTER_HANDLE_REMOTE_DATA) ) {
  1112. //
  1113. // If the driver can't convert devmode user's can't set devmode from remote m/c
  1114. //
  1115. pDevMode = ConvertDevModeToSpecifiedVersion(pIniPrinter,
  1116. pDevMode,
  1117. NULL,
  1118. NULL,
  1119. CURRENT_VERSION);
  1120. }
  1121. }
  1122. SplInSem();
  1123. pIniSpooler = pIniPrinter->pIniSpooler;
  1124. SPLASSERT(pIniPrinter->signature == IP_SIGNATURE );
  1125. SPLASSERT(pIniSpooler->signature == ISP_SIGNATURE );
  1126. if (pSpool->pIniPrinter->Status & PRINTER_ZOMBIE_OBJECT) {
  1127. LastError = ERROR_PRINTER_DELETED;
  1128. goto Cleanup;
  1129. }
  1130. if ( !ValidateLevelAndSecurityAccesses(pSpool,
  1131. Level,
  1132. pPrinterInfo,
  1133. Command,
  1134. &AccessRequired,
  1135. &SecurityInformation) ){
  1136. bReturn = FALSE;
  1137. goto Cleanup;
  1138. }
  1139. //
  1140. // Level 7 & publishing levels
  1141. //
  1142. if (Level == 7) {
  1143. if ( !(pIniPrinter->pIniSpooler->SpoolerFlags & SPL_TYPE_CACHE)) {
  1144. if (pPrinterInfo7->dwAction != DSPRINT_PUBLISH &&
  1145. pPrinterInfo7->dwAction != DSPRINT_UNPUBLISH &&
  1146. pPrinterInfo7->dwAction != DSPRINT_REPUBLISH &&
  1147. pPrinterInfo7->dwAction != DSPRINT_UPDATE) {
  1148. LastError = ERROR_INVALID_PARAMETER;
  1149. bReturn = FALSE;
  1150. goto Cleanup;
  1151. }
  1152. DBGMSG(DBG_EXEC, ("SplSetPrinter: DS Action %d: %ws %ws",
  1153. pPrinterInfo7->dwAction,
  1154. pIniPrinter->pName,
  1155. pIniPrinter->pszObjectGUID ?
  1156. pIniPrinter->pszObjectGUID : L"<NULL>"));
  1157. bUpdateDsSpoolerKey = TRUE;
  1158. } else {
  1159. //
  1160. // For connections, we rely directly on pPrinterInfo7->dwAction because
  1161. // then we cannot determine a pending publishing state based on attributes and GUID.
  1162. // If the remote printer is in Pending publishing, we need to save this in dwAction.
  1163. //
  1164. if (!pIniPrinter->pszObjectGUID || !pPrinterInfo7->pszObjectGUID) {
  1165. FreeSplStr(pIniPrinter->pszObjectGUID);
  1166. pIniPrinter->pszObjectGUID = NULL;
  1167. dwPrinterVector |= BIT(I_PRINTER_OBJECT_GUID);
  1168. } else if (wcscmp(pIniPrinter->pszObjectGUID, pPrinterInfo7->pszObjectGUID)) {
  1169. FreeSplStr(pIniPrinter->pszObjectGUID);
  1170. }
  1171. if ( pPrinterInfo7->pszObjectGUID ) {
  1172. if (!(pIniPrinter->pszObjectGUID = AllocSplStr(pPrinterInfo7->pszObjectGUID))) {
  1173. bReturn = FALSE;
  1174. goto Cleanup;
  1175. }
  1176. }
  1177. pIniPrinter->dwAction = pPrinterInfo7->dwAction;
  1178. dwPrinterVector |= BIT(I_PRINTER_OBJECT_GUID);
  1179. }
  1180. goto Finish;
  1181. } else if (Level != 3 && Level != 0) {
  1182. bUpdateDsSpoolerKey = TRUE;
  1183. }
  1184. //
  1185. // We need to do this for Level 0, 2, 3, 4, 5
  1186. // (except for level 3 which is security case)
  1187. //
  1188. if ( Level != 3 && pSpool->hPort ) {
  1189. if ( pSpool->hPort == INVALID_PORT_HANDLE ) {
  1190. //
  1191. // If this value is 0, then when we return GetLastError,
  1192. // the client will think we succeeded.
  1193. //
  1194. SPLASSERT( pSpool->OpenPortError );
  1195. LastError = pSpool->OpenPortError;
  1196. goto Cleanup;
  1197. } else {
  1198. bReturn = SetPrinter(pSpool->hPort,
  1199. Level,
  1200. pPrinterInfo,
  1201. Command);
  1202. if ( !Level )
  1203. goto Cleanup;
  1204. }
  1205. }
  1206. if ( Level != 6 && Level != 0 ) {
  1207. pTempIniPrinter = (PINIPRINTER) AllocSplMem(sizeof(INIPRINTER));
  1208. if ( !pTempIniPrinter )
  1209. goto Cleanup;
  1210. CopyMemory(pTempIniPrinter, pIniPrinter, sizeof(INIPRINTER));
  1211. }
  1212. //
  1213. // The actual processing begins here
  1214. //
  1215. if ( !Level && !Command ) {
  1216. bReturn = SetLocalPrinterSTRESS(pIniPrinter,
  1217. (PPRINTER_INFO_STRESS)pPrinterInfo);
  1218. goto Cleanup;
  1219. } else if ( !Level ) {
  1220. bReturn = SetLocalPrinter0(pIniPrinter, Command);
  1221. goto Cleanup;
  1222. } else if ( Level == 6 ) {
  1223. bReturn = SetPrinterStatus(pIniPrinter,
  1224. ((LPPRINTER_INFO_6)pPrinterInfo)->dwStatus);
  1225. goto Cleanup;
  1226. } else {
  1227. if ( !ValidateAndBuildSetPrinterRequest(pIniPrinter,
  1228. pTempIniPrinter,
  1229. pPrinterInfo,
  1230. Level,
  1231. SecurityInformation,
  1232. &bSecurityChg,
  1233. &bNameChg,
  1234. &bAttributeChg,
  1235. &pszNewPrinterName,
  1236. &pKeyData) ) {
  1237. bReturn = FALSE;
  1238. goto Cleanup;
  1239. } // else we follow thru rest of code since all valiations succeded
  1240. // Just a flag stating whether we have a new port
  1241. bNewPort = NewPort(pKeyData, pIniPrinter);
  1242. if (bNewPort) {
  1243. dwPrinterVector |= BIT(I_PRINTER_PORT_NAME);
  1244. }
  1245. }
  1246. //
  1247. // --------------------All validation done---------------------------
  1248. //
  1249. //
  1250. // Now set security information; Remember we have
  1251. // a valid SecurityDescriptor and "SecurityInformation
  1252. // is non-zero at this point. We have validated this
  1253. // information
  1254. //
  1255. if ( bSecurityChg ) {
  1256. if ( SetPrinterSecurityDescriptor(SecurityInformation,
  1257. pTempIniPrinter->pSecurityDescriptor,
  1258. &pIniPrinter->pSecurityDescriptor) ) {
  1259. dwPrinterVector |= BIT(I_PRINTER_SECURITY_DESCRIPTOR);
  1260. bShareUpdate = TRUE;
  1261. } else {
  1262. bReturn = FALSE;
  1263. goto Cleanup;
  1264. }
  1265. }
  1266. // Can we avoid doing this if bNewPort == NULL?
  1267. if ( Level == 2 || Level == 5 ) {
  1268. //
  1269. // bi-dir associate pIniPrinter with ports inside pKeyData.
  1270. //
  1271. bReturn = SetPrinterPorts(pSpool, pIniPrinter, pKeyData);
  1272. if ( !bReturn )
  1273. goto Cleanup;
  1274. }
  1275. if ( bAttributeChg ) {
  1276. if ( !(pTempIniPrinter->Attributes & PRINTER_ATTRIBUTE_ENABLE_DEVQ) &&
  1277. pIniPrinter->cJobs) {
  1278. pIniJob = pIniPrinter->pIniFirstJob;
  1279. while (pIniJob) {
  1280. if (pIniJob->Status & JOB_BLOCKED_DEVQ) {
  1281. PNOTIFYVECTOR pNotifyVector = &NVJobStatus;
  1282. InterlockedAnd((LONG*)&(pIniJob->Status), ~JOB_BLOCKED_DEVQ);
  1283. if( pIniJob->pStatus ){
  1284. FreeSplStr(pIniJob->pStatus);
  1285. pIniJob->pStatus = NULL;
  1286. pNotifyVector = &NVJobStatusAndString;
  1287. }
  1288. SetPrinterChange(pIniJob->pIniPrinter,
  1289. pIniJob,
  1290. *pNotifyVector,
  1291. PRINTER_CHANGE_SET_JOB,
  1292. pIniJob->pIniPrinter->pIniSpooler);
  1293. }
  1294. pIniJob = pIniJob->pIniNextJob;
  1295. }
  1296. }
  1297. }
  1298. //
  1299. // The comment must be changed here since ShareThisPrinter
  1300. // will look at pComment when the printer is reshared.
  1301. //
  1302. if ( Level == 2 &&
  1303. pIniPrinter->pComment != pTempIniPrinter->pComment ) {
  1304. FreeSplStr(pIniPrinter->pComment);
  1305. pIniPrinter->pComment = pTempIniPrinter->pComment;
  1306. dwPrinterVector |= BIT(I_PRINTER_COMMENT);
  1307. if (pTempIniPrinter->Attributes & PRINTER_ATTRIBUTE_SHARED) {
  1308. bShareUpdate = TRUE;
  1309. }
  1310. }
  1311. //
  1312. // Change printer name if different
  1313. //
  1314. if ( bNameChg ) {
  1315. pszOldPrinterName = AllocSplStr(pIniPrinter->pName);
  1316. if (!pszOldPrinterName && pIniPrinter->pName) {
  1317. bReturn = FALSE;
  1318. goto Cleanup;
  1319. }
  1320. ChangePrinterName(pszNewPrinterName, pIniPrinter, pIniSpooler,
  1321. &dwPrinterVector);
  1322. pszNewPrinterName = NULL;
  1323. //
  1324. // The print share must be recreated since there's no way
  1325. // to change the path without deleting and creating a new one.
  1326. //
  1327. bShareRecreate = TRUE;
  1328. }
  1329. //
  1330. // If Share name changed force update
  1331. //
  1332. if ( pIniPrinter->pShareName != pTempIniPrinter->pShareName ) {
  1333. bShareRecreate = TRUE;
  1334. }
  1335. if ( bAttributeChg || bShareUpdate || bShareRecreate ) {
  1336. OldAttributes = pIniPrinter->Attributes;
  1337. pIniPrinter->Attributes = pTempIniPrinter->Attributes;
  1338. bReturn = ChangePrinterAttributes(pIniPrinter->Attributes,
  1339. OldAttributes,
  1340. pIniPrinter,
  1341. pIniSpooler,
  1342. pTempIniPrinter->pShareName,
  1343. bShareRecreate,
  1344. bShareUpdate);
  1345. if (!bReturn) {
  1346. LastError = GetLastError();
  1347. }
  1348. if (pIniPrinter->Attributes != OldAttributes) {
  1349. dwPrinterVector |= BIT(I_PRINTER_ATTRIBUTES);
  1350. }
  1351. }
  1352. if ( Level == 2 ) {
  1353. ProcessSetPrinter2(pIniPrinter,
  1354. pTempIniPrinter,
  1355. pPrinterInfo2,
  1356. &dwPrinterVector,
  1357. pDevMode);
  1358. }
  1359. Finish:
  1360. // Sometimes SetPrinter can fail certain calls after it has modified some parameters.
  1361. // For instance, we may have failed to update some sharing fields. If we get to this
  1362. // point (or anywhere after the last goto Cleanup), then we need to update the ds keys.
  1363. // We should really clean up SetPrinter so it undoes everything, but we don't have enough time
  1364. // to fix it properly before NT6.
  1365. bDataChanged = TRUE;
  1366. CHECK_SCHEDULER();
  1367. // Can we avoid doing this if dwPrinterVector == NULL?
  1368. UpdatePrinterIni( pIniPrinter, UPDATE_CHANGEID );
  1369. // Can we avoid doing this if dwPrinterVector == NULL?
  1370. UpdateWinIni( pIniPrinter ); // So the port on the device is correct
  1371. //
  1372. // Log event that the SetPrinter was done.
  1373. //
  1374. INCPRINTERREF(pIniPrinter);
  1375. SplLogEvent(pIniSpooler, LOG_INFO, MSG_PRINTER_SET, TRUE, pIniPrinter->pName, NULL);
  1376. DECPRINTERREF(pIniPrinter);
  1377. NotifyVector[PRINTER_NOTIFY_TYPE] |= dwPrinterVector;
  1378. //
  1379. // Indicate that a change has occurred.
  1380. //
  1381. SetPrinterChange(pIniPrinter,
  1382. NULL,
  1383. NotifyVector,
  1384. PRINTER_CHANGE_SET_PRINTER,
  1385. pIniSpooler);
  1386. Cleanup:
  1387. SplInSem();
  1388. if ( LastError != ERROR_SUCCESS ) {
  1389. SetLastError(LastError);
  1390. bReturn = FALSE;
  1391. }
  1392. CleanupSetPrinter(pIniPrinter, pTempIniPrinter, pKeyData,
  1393. Level, bReturn);
  1394. if (bDataChanged) {
  1395. INCPRINTERREF(pIniPrinter);
  1396. LeaveSplSem();
  1397. SplOutSem();
  1398. //
  1399. // If the printer driver changed
  1400. // Call the printer driver to initialize itself
  1401. //
  1402. if (dwPrinterVector & BIT(I_PRINTER_DRIVER_NAME)) {
  1403. PDEVMODE pDevMode = NULL;
  1404. PrinterDriverEvent(pIniPrinter, PRINTER_EVENT_INITIALIZE, (LPARAM)NULL, &dwPrnEvntError);
  1405. //
  1406. // If the driver name changed then convert the devmode to the new driver's
  1407. // devmode. Note this must be done after the printer event initialize
  1408. // because the driver is not able to handle a convert devmode call before
  1409. // being initialized. Also if the conversion fails we potentially end up
  1410. // having the old devmode in the registry. We could null out the devmode
  1411. // but is it better to have a bad old devmode in the registry rather than a null
  1412. // devmode. A null devmode is more dangerous because an application may
  1413. // get really confused with a null devmode rather than a bad devmode
  1414. // which the driver will eventually fix, because they have to handle foreign
  1415. // devmodes any way.
  1416. //
  1417. EnterSplSem();
  1418. //
  1419. // Now convert the devmode to the driver specific devmode.
  1420. //
  1421. pDevMode = ConvertDevModeToSpecifiedVersion(pIniPrinter,
  1422. pIniPrinter->pDevMode,
  1423. NULL,
  1424. NULL,
  1425. CURRENT_VERSION);
  1426. //
  1427. // If a new devmode was returned then release the current printer's
  1428. // devmode and save the new devmode.
  1429. //
  1430. if (pDevMode) {
  1431. FreeSplMem(pIniPrinter->pDevMode);
  1432. pIniPrinter->pDevMode = pDevMode;
  1433. pIniPrinter->cbDevMode = pDevMode->dmSize + pDevMode->dmDriverExtra;
  1434. }
  1435. //
  1436. // Write the newly converted devmode to the registry again.
  1437. //
  1438. UpdatePrinterIni( pIniPrinter, UPDATE_CHANGEID );
  1439. LeaveSplSem();
  1440. }
  1441. //
  1442. // If the printer attributes changed, call the driver with the two
  1443. // different sets of attributes, this is to allow the fax driver to
  1444. // start up the fax service when a printer gets shared out.
  1445. //
  1446. if (dwPrinterVector & BIT(I_PRINTER_ATTRIBUTES)) {
  1447. PRINTER_EVENT_ATTRIBUTES_INFO AttributesInfo = {
  1448. sizeof(PRINTER_EVENT_ATTRIBUTES_INFO),
  1449. OldAttributes,
  1450. pIniPrinter->Attributes
  1451. };
  1452. PrinterDriverEvent(pIniPrinter, PRINTER_EVENT_ATTRIBUTES_CHANGED, (LPARAM)&AttributesInfo, &dwPrnEvntError);
  1453. }
  1454. EnterSplSem();
  1455. SplInSem();
  1456. DECPRINTERREF(pIniPrinter);
  1457. }
  1458. // Don't update if this is from cache
  1459. if (!bDataChanged || ((Level == 2 || Level == 5) && !dwPrinterVector) ||
  1460. (pIniPrinter->pIniSpooler->SpoolerFlags & SPL_TYPE_CACHE)) {
  1461. bUpdateDsSpoolerKey = FALSE;
  1462. } else if (bUpdateDsSpoolerKey) {
  1463. if (Level != 7)
  1464. {
  1465. //
  1466. // Update unly values that changed.
  1467. //
  1468. UpdateDsSpoolerKey(hPrinter, dwPrinterVector);
  1469. } else if (pPrinterInfo7->dwAction != DSPRINT_UNPUBLISH)
  1470. {
  1471. //
  1472. // Update the all values in Registry for level 7.
  1473. //
  1474. UpdateDsSpoolerKey(hPrinter, 0xffffffff);
  1475. }
  1476. //
  1477. // Reset Driver DS Properties if driver changed
  1478. //
  1479. if (dwPrinterVector & BIT(I_PRINTER_DRIVER_NAME)) {
  1480. INCPRINTERREF(pIniPrinter);
  1481. LeaveSplSem();
  1482. //
  1483. // This calls SetPrinterDs with DSPRINT_UPDATE anyway.
  1484. //
  1485. RecreateDsKey(hPrinter, SPLDS_DRIVER_KEY);
  1486. EnterSplSem();
  1487. DECPRINTERREF(pIniPrinter);
  1488. } else if (Level != 7 || pPrinterInfo7->dwAction != DSPRINT_UNPUBLISH) {
  1489. //
  1490. // If the driver didn't change, query the driver again for capabilities.
  1491. //
  1492. UpdateDsDriverKey(hPrinter);
  1493. }
  1494. }
  1495. if (bUpdateDsSpoolerKey) {
  1496. if (pIniPrinter->DsKeyUpdateForeground || (Level == 7 && pPrinterInfo7->dwAction == DSPRINT_UNPUBLISH)) {
  1497. if (Level == 7) {
  1498. if ((dwResult = SetPrinterDs(hPrinter, pPrinterInfo7->dwAction, FALSE)) != ERROR_SUCCESS) {
  1499. SetLastError(dwResult);
  1500. bReturn = FALSE;
  1501. }
  1502. } else {
  1503. //
  1504. // Update only, in the background thread.
  1505. //
  1506. SetPrinterDs(hPrinter, DSPRINT_UPDATE, FALSE);
  1507. }
  1508. }
  1509. }
  1510. LeaveSplSem();
  1511. SplOutSem();
  1512. if ( pDevMode && pDevMode != pPrinterInfo2->pDevMode )
  1513. FreeSplMem(pDevMode);
  1514. if ( pszOldPrinterName ) {
  1515. FreeSplStr(pszOldPrinterName);
  1516. }
  1517. FreeSplStr(pszNewPrinterName);
  1518. return bReturn;
  1519. }
  1520. PRINTER_SECURITY_STATUS
  1521. SetPrinterSecurity(
  1522. SECURITY_INFORMATION SecurityInformation,
  1523. PINIPRINTER pIniPrinter,
  1524. PSECURITY_DESCRIPTOR pSecurityDescriptor)
  1525. {
  1526. DWORD dwSize;
  1527. if (!pSecurityDescriptor)
  1528. return SECURITY_FAIL;
  1529. if (pIniPrinter->pSecurityDescriptor) {
  1530. dwSize = GetSecurityDescriptorLength(pIniPrinter->pSecurityDescriptor);
  1531. if (dwSize == GetSecurityDescriptorLength(pSecurityDescriptor)) {
  1532. if (!memcmp(pSecurityDescriptor,
  1533. pIniPrinter->pSecurityDescriptor,
  1534. dwSize)) {
  1535. return SECURITY_NOCHANGE;
  1536. }
  1537. }
  1538. }
  1539. if( !SetPrinterSecurityDescriptor( SecurityInformation,
  1540. pSecurityDescriptor,
  1541. &pIniPrinter->pSecurityDescriptor ) ) {
  1542. DBGMSG(DBG_WARNING, ("SetPrinterSecurityDescriptor failed. Error = %d\n",
  1543. GetLastError()));
  1544. return SECURITY_FAIL;
  1545. }
  1546. UpdatePrinterIni(pIniPrinter, UPDATE_CHANGEID);
  1547. return SECURITY_SUCCESS;
  1548. }
  1549. VOID
  1550. RegClearKey(
  1551. HKEY hKey,
  1552. PINISPOOLER pIniSpooler
  1553. )
  1554. {
  1555. DWORD dwError;
  1556. WCHAR szValue[4*MAX_PATH];
  1557. DWORD cchValue;
  1558. while (TRUE) {
  1559. cchValue = COUNTOF(szValue);
  1560. dwError = SplRegEnumValue( hKey,
  1561. 0,
  1562. szValue,
  1563. &cchValue,
  1564. NULL,
  1565. NULL,
  1566. NULL,
  1567. pIniSpooler );
  1568. if( dwError != ERROR_SUCCESS ){
  1569. if( dwError != ERROR_NO_MORE_ITEMS ){
  1570. DBGMSG( DBG_ERROR, ( "RegClearKey: Failed %d\n", dwError ));
  1571. }
  1572. break;
  1573. }
  1574. dwError = SplRegDeleteValue( hKey, szValue, pIniSpooler );
  1575. if( dwError != ERROR_SUCCESS ){
  1576. DBGMSG( DBG_ERROR, ( "RegDeleteValue: %s Failed %d\n",
  1577. szValue, dwError ));
  1578. break;
  1579. }
  1580. }
  1581. }
  1582. BOOL
  1583. ChangePrinterAttributes(
  1584. DWORD dNewAttributes,
  1585. DWORD dOldAttributes,
  1586. PINIPRINTER pIniPrinter,
  1587. PINISPOOLER pIniSpooler,
  1588. LPWSTR pszNewShareName,
  1589. BOOL bShareRecreate,
  1590. BOOL bShareUpdate
  1591. )
  1592. /*++
  1593. Routine Description:
  1594. Changes printer attributes by validating sharing information.
  1595. Already the validated attributes are set, we want to validate
  1596. by changing the share information
  1597. Arguments:
  1598. dNewAttributes - New attributes specified on SetPrinter call
  1599. dOldAttributes - pIniPrinter->Attributes before the call
  1600. pIniPrinter - of the printer we are changing attributes
  1601. pIniSpooler - Spooler that owns printer
  1602. pszNewShareName - the share name that will be set if SetPrinter succeeds
  1603. bShareRecreate - Share must be recreated because the printer or share
  1604. name changed.
  1605. bShareUpdate - Share just needs to be updated, since comment / SD changed.
  1606. Return Value:
  1607. DWORD TRUE on success, FALSE else.
  1608. --*/
  1609. {
  1610. BOOL Shared, bReturn = TRUE;
  1611. //
  1612. // We are going to have to be able to restore the attributes if the share
  1613. // modification fails. We need to set the current attributes now because
  1614. // the NetSharexxx is going to call OpenPrinter, and possibly an AddJob
  1615. // which needs the correct Attributes.
  1616. //
  1617. if (dNewAttributes & PRINTER_ATTRIBUTE_SHARED) {
  1618. if (!(dOldAttributes & PRINTER_ATTRIBUTE_SHARED)) {
  1619. pIniPrinter->Attributes |= PRINTER_ATTRIBUTE_SHARED;
  1620. Shared = ShareThisPrinter( pIniPrinter, pszNewShareName, TRUE );
  1621. if ( !Shared ) {
  1622. pIniPrinter->Attributes = dOldAttributes;
  1623. bReturn = FALSE;
  1624. }
  1625. } else {
  1626. //
  1627. // We are shared, and so is the old one. If share name changed
  1628. // we have to remove old share and reshare.
  1629. //
  1630. if ( bShareRecreate ) {
  1631. if (ShareThisPrinter(pIniPrinter,
  1632. pIniPrinter->pShareName,
  1633. FALSE)) {
  1634. #if DBG
  1635. WCHAR szError[256];
  1636. StringCchPrintf(szError, COUNTOF(szError), L"Error %d, removing share", GetLastError());
  1637. //
  1638. // Error: the printer shouldn't be shared at this
  1639. // point.
  1640. //
  1641. INCPRINTERREF(pIniPrinter);
  1642. SplLogEvent(pIniSpooler,
  1643. LOG_ERROR,
  1644. MSG_SHARE_FAILED,
  1645. TRUE,
  1646. L"SetLocalPrinter ShareThisPrinter FALSE",
  1647. pIniPrinter->pName,
  1648. pIniPrinter->pShareName,
  1649. szError,
  1650. NULL);
  1651. DECPRINTERREF(pIniPrinter);
  1652. #endif
  1653. bReturn = FALSE;
  1654. } else if (!ShareThisPrinter(pIniPrinter,
  1655. pszNewShareName,
  1656. TRUE)) {
  1657. #if DBG
  1658. WCHAR szError[256];
  1659. StringCchPrintf(szError, COUNTOF(szError), L"Error %d, adding share", GetLastError());
  1660. //
  1661. // Error: the printer shouldn't be shared at this
  1662. // point.
  1663. //
  1664. INCPRINTERREF(pIniPrinter);
  1665. SplLogEvent(pIniSpooler,
  1666. LOG_ERROR,
  1667. MSG_SHARE_FAILED,
  1668. TRUE,
  1669. L"SetLocalPrinter ShareThisPrinter TRUE",
  1670. pIniPrinter->pName,
  1671. pIniPrinter->pShareName,
  1672. szError,
  1673. NULL);
  1674. DECPRINTERREF(pIniPrinter);
  1675. #endif
  1676. pIniPrinter->Attributes &= ~PRINTER_ATTRIBUTE_SHARED;
  1677. pIniPrinter->Status |= PRINTER_WAS_SHARED;
  1678. bReturn = FALSE;
  1679. }
  1680. } else if ( bShareUpdate ) {
  1681. //
  1682. // If comment/description changed then we just do a NetShareSet
  1683. //
  1684. bReturn = SetPrinterShareInfo(pIniPrinter);
  1685. }
  1686. }
  1687. } else if (dOldAttributes & PRINTER_ATTRIBUTE_SHARED) {
  1688. Shared = ShareThisPrinter(pIniPrinter, pIniPrinter->pShareName, FALSE);
  1689. if (!Shared) {
  1690. pIniPrinter->Attributes &= ~PRINTER_ATTRIBUTE_SHARED;
  1691. pIniPrinter->Status |= PRINTER_WAS_SHARED;
  1692. CreateServerThread();
  1693. } else {
  1694. pIniPrinter->Attributes = dOldAttributes;
  1695. bReturn = FALSE;
  1696. }
  1697. }
  1698. if (((dOldAttributes & PRINTER_ATTRIBUTE_WORK_OFFLINE) &&
  1699. !(dNewAttributes & PRINTER_ATTRIBUTE_WORK_OFFLINE) ) ||
  1700. (!(dOldAttributes & PRINTER_ATTRIBUTE_WORK_OFFLINE) &&
  1701. (dNewAttributes & PRINTER_ATTRIBUTE_WORK_OFFLINE) ) ) {
  1702. WritePrinterOnlineStatusInCurrentConfig(pIniPrinter);
  1703. }
  1704. return bReturn;
  1705. }