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.

1272 lines
37 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name :
  4. rdpprutl.c
  5. Abstract:
  6. Contains print redirection supporting routines for the TS printer
  7. redirection user-mode component.
  8. This is a supporting module. The main module is umrdpdr.c.
  9. Author:
  10. TadB
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #include <winspool.h>
  16. #include <setupapi.h>
  17. #include "printui.h"
  18. #include "drdbg.h"
  19. #include <regapi.h>
  20. #include <aclapi.h>
  21. #include "errorlog.h"
  22. #include "tsnutl.h"
  23. #include <wlnotify.h>
  24. #include <wchar.h>
  25. ////////////////////////////////////////////////////////
  26. //
  27. // Defines
  28. //
  29. #define SETUPAPILIBNAME TEXT("setupapi.dll")
  30. #define ISNUM(c) ((c>='0')&&(c<='9'))
  31. ////////////////////////////////////////////////////////
  32. //
  33. // Globals
  34. //
  35. extern DWORD GLOBAL_DEBUG_FLAGS;
  36. HANDLE SetupAPILibHndl = NULL;
  37. FARPROC SetupOpenInfFileFunc = NULL;
  38. FARPROC SetupFindFirstLineFunc = NULL;
  39. FARPROC SetupFindNextLineFunc = NULL;
  40. FARPROC SetupGetStringFieldFunc = NULL;
  41. ////////////////////////////////////////////////////////
  42. //
  43. // Internal Prototypes
  44. //
  45. // Loads setupapi.dll and related functions.
  46. BOOL LoadSetupAPIDLLFunctions();
  47. void DeleteTSPrinters(
  48. IN PRINTER_INFO_5 *pPrinterInfo,
  49. IN DWORD count
  50. );
  51. BOOL
  52. RDPDRUTL_Initialize(
  53. IN HANDLE hTokenForLoggedOnUser
  54. )
  55. /*++
  56. Routine Description:
  57. Initialize this module. This must be called prior to any other functions
  58. in this module being called.
  59. Arguments:
  60. hTokenForLoggedOnUser - This is the token for the logged in user.
  61. Return Value:
  62. Returns TRUE on success. FALSE, otherwise.
  63. --*/
  64. {
  65. DBGMSG(DBG_TRACE, ("RDPPRUTL:RDPDRUTL_Initialize.\n"));
  66. //
  67. // Make sure we don't get called twice.
  68. //
  69. ASSERT(SetupAPILibHndl == NULL);
  70. //
  71. // Load Setup API Library.
  72. //
  73. DBGMSG(DBG_TRACE, ("RDPPRUTL:RDPDRUTL_Initialize done.\n"));
  74. // Just return TRUE for now.
  75. return TRUE;
  76. }
  77. void
  78. RDPDRUTL_Shutdown()
  79. /*++
  80. Routine Description:
  81. Close down this module. Right now, we just need to shut down the
  82. background thread.
  83. Arguments:
  84. Return Value:
  85. Returns TRUE on success. FALSE, otherwise.
  86. --*/
  87. {
  88. DBGMSG(DBG_TRACE, ("RDPPRUTL:RDPDRUTL_Shutdown.\n"));
  89. //
  90. // Release the Setup API library.
  91. //
  92. if (SetupAPILibHndl != NULL) {
  93. FreeLibrary(SetupAPILibHndl);
  94. SetupAPILibHndl = NULL;
  95. }
  96. //
  97. // Zero the entry points.
  98. //
  99. SetupOpenInfFileFunc = NULL;
  100. SetupFindFirstLineFunc = NULL;
  101. SetupFindNextLineFunc = NULL;
  102. SetupGetStringFieldFunc = NULL;
  103. //
  104. // Load Setup API Library.
  105. //
  106. DBGMSG(DBG_TRACE, ("RDPPRUTL:RDPDRUTL_Shutdown done.\n"));
  107. }
  108. BOOL
  109. LoadSetupAPIDLLFunctions()
  110. /*++
  111. Routine Description:
  112. Loads setupapi.dll and related functions.
  113. Arguments:
  114. Return Value:
  115. Returns TRUE on success. FALSE, otherwise.
  116. --*/
  117. {
  118. BOOL result;
  119. //
  120. // Only load if we are not already loaded.
  121. //
  122. if (SetupAPILibHndl == NULL) {
  123. SetupAPILibHndl = LoadLibrary(SETUPAPILIBNAME);
  124. result = (SetupAPILibHndl != NULL);
  125. if (!result) {
  126. DBGMSG(DBG_ERROR,
  127. ("RDPPRUTL:Unable to load SETUPAPI DLL. Error: %ld\n",
  128. GetLastError()));
  129. }
  130. else {
  131. SetupOpenInfFileFunc = GetProcAddress(SetupAPILibHndl,
  132. "SetupOpenInfFileW");
  133. SetupFindFirstLineFunc = GetProcAddress(SetupAPILibHndl,
  134. "SetupFindFirstLineW");
  135. SetupFindNextLineFunc = GetProcAddress(SetupAPILibHndl,
  136. "SetupFindNextLine");
  137. SetupGetStringFieldFunc = GetProcAddress(SetupAPILibHndl,
  138. "SetupGetStringFieldW");
  139. //
  140. // If we failed to load any of the functions.
  141. //
  142. if ((SetupOpenInfFileFunc == NULL) ||
  143. (SetupFindFirstLineFunc == NULL) ||
  144. (SetupFindNextLineFunc == NULL) ||
  145. (SetupGetStringFieldFunc == NULL)) {
  146. DBGMSG(DBG_ERROR,
  147. ("RDPPRUTL:Failed to load setup func. Error: %ld\n",
  148. GetLastError()));
  149. FreeLibrary(SetupAPILibHndl);
  150. SetupAPILibHndl = NULL;
  151. SetupOpenInfFileFunc = NULL;
  152. SetupFindFirstLineFunc = NULL;
  153. SetupFindNextLineFunc = NULL;
  154. SetupGetStringFieldFunc = NULL;
  155. result = FALSE;
  156. }
  157. else {
  158. result = TRUE;
  159. }
  160. }
  161. }
  162. else {
  163. result = TRUE;
  164. }
  165. return result;
  166. }
  167. BOOL
  168. RDPDRUTL_PrinterIsTS(
  169. IN PWSTR printerName
  170. )
  171. /*++
  172. Routine Description:
  173. Return whether an open printer is a TSRDP printer.
  174. Arguments:
  175. printerName - Name of printer to check.
  176. Return Value:
  177. Returns TRUE if the printer is a TS printer. Otherwise, FALSE is
  178. returned.
  179. --*/
  180. {
  181. DWORD regValueDataType;
  182. DWORD sessionID;
  183. DWORD bufSize;
  184. HANDLE hPrinter;
  185. PRINTER_DEFAULTS defaults = {NULL, NULL, PRINTER_ALL_ACCESS};
  186. BOOL result;
  187. DBGMSG(DBG_TRACE, ("RDPPRUTL:Entering RDPDRUTL_PrinterIsTS.\n"));
  188. //
  189. // Open the printer.
  190. //
  191. result = OpenPrinter(printerName, &hPrinter, &defaults);
  192. //
  193. // See if a session id for the printer defined in its associated
  194. // registry information.
  195. //
  196. if (result) {
  197. result = GetPrinterData(
  198. hPrinter,
  199. DEVICERDR_SESSIONID,
  200. &regValueDataType,
  201. (PBYTE)&sessionID, sizeof(sessionID),
  202. &bufSize
  203. ) == ERROR_SUCCESS;
  204. ClosePrinter(hPrinter);
  205. }
  206. else {
  207. DBGMSG(DBG_ERROR, ("RDPPRUTL:Error opening %ws: %ld.\n",
  208. printerName, GetLastError()));
  209. }
  210. DBGMSG(DBG_TRACE, ("RDPPRUTL:Exiting RDPDRUTL_PrinterIsTS.\n"));
  211. return result;
  212. }
  213. BOOL
  214. RDPDRUTL_MapPrintDriverName(
  215. IN PCWSTR driverName,
  216. IN PCWSTR infName,
  217. IN PCWSTR sectionName,
  218. IN ULONG srcFieldOfs,
  219. IN ULONG dstFieldOfs,
  220. OUT PWSTR retBuf,
  221. IN DWORD retBufSize,
  222. OUT PDWORD requiredSize
  223. )
  224. /*++
  225. Routine Description:
  226. Map a client-side printer driver name to its server-side equivalent,
  227. using the specified INF and section name.
  228. Arguments:
  229. driverName - Driver name to map.
  230. infName - Name of INF mapping file.
  231. sectionName - Name of INF mapping section.
  232. srcFieldOfs - In mapping section, the field offset (0-based)
  233. of the source name.
  234. dstFieldOfs - In mapping section, the field offset (0-based)
  235. of the resulting name.
  236. retBuf - Mapped driver name.
  237. retBufSize - Size in characters of retBuf.
  238. requiredSize - Required size (IN CHARACTERS) of return buffer is
  239. returned here. GetLastError() will return
  240. ERROR_INSUFFICIENT_BUFFER if the supplied
  241. buffer was too small for the operation
  242. to successfully complete.
  243. Return Value:
  244. Returns TRUE on success. FALSE, otherwise. If there is not room in
  245. retBuf, then FALSE is returned and GetLastError() will return
  246. ERROR_INSUFFICIENT_BUFFER.
  247. Extended error information can be retrieved by a call to GetLastError.
  248. --*/
  249. {
  250. HINF inf;
  251. PWSTR returnString = NULL;
  252. BOOL outOfEntries;
  253. BOOL result = TRUE;
  254. INFCONTEXT infContext;
  255. WCHAR *parms[1];
  256. DBGMSG(DBG_TRACE, ("RDPPRUTL:Entering RDPDRUTL_MapPrintDriverName.\n"));
  257. //
  258. // Just get out fast if we can't load the setup API's
  259. //
  260. if (!LoadSetupAPIDLLFunctions()) {
  261. //
  262. // Need to make sure it didn't fail because of insufficient buffer
  263. // because that has meaning when returned from this function.
  264. //
  265. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  266. SetLastError(ERROR_NOT_ENOUGH_SERVER_MEMORY);
  267. }
  268. return FALSE;
  269. }
  270. //
  271. // Open the INF.
  272. //
  273. inf = SetupOpenInfFile(
  274. infName, NULL,
  275. INF_STYLE_OLDNT | INF_STYLE_WIN4,
  276. NULL
  277. );
  278. //
  279. // Get the first entry from the INF section.
  280. //
  281. if (inf != INVALID_HANDLE_VALUE) {
  282. memset(&infContext, 0, sizeof(infContext));
  283. outOfEntries = !SetupFindFirstLine(inf, sectionName, NULL, &infContext);
  284. if (!outOfEntries) {
  285. result = SetupGetStringField(&infContext, srcFieldOfs, retBuf,retBufSize,
  286. requiredSize);
  287. //
  288. // This API returns success with no error code for a NULL buffer.
  289. //
  290. if (result && (retBuf == NULL)) {
  291. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  292. result = FALSE;
  293. }
  294. }
  295. else {
  296. DBGMSG(DBG_ERROR, ("RDPPRUTL:SetupFindFirstLine failed with %08X.\n", GetLastError()));
  297. result = FALSE;
  298. }
  299. }
  300. else {
  301. DBGMSG(DBG_ERROR, ("RDPPRUTL:SetupOpenInfFile failed with %08X.\n",
  302. GetLastError()));
  303. outOfEntries = TRUE;
  304. result = FALSE;
  305. }
  306. //
  307. // Look through the INF for a matching name in the INF mapping section.
  308. //
  309. while (result && !outOfEntries) {
  310. //
  311. // If we have a match, then read the first field out of the current entry.
  312. // This is the information that we should return.
  313. //
  314. if (!wcscmp(retBuf, driverName)) {
  315. result = SetupGetStringField(&infContext, dstFieldOfs, retBuf,retBufSize,
  316. requiredSize);
  317. if (result) {
  318. DBGMSG(DBG_TRACE, ("RDPPRUTL:Found match %ws in INF for %ws.\n",
  319. driverName, retBuf));
  320. }
  321. else {
  322. DBGMSG(DBG_TRACE, ("RDPPRUTL:Error processing INF for %ws.\n",
  323. driverName));
  324. }
  325. break;
  326. }
  327. //
  328. // Get the next entry.
  329. //
  330. outOfEntries = !SetupFindNextLine(&infContext, &infContext);
  331. if (!outOfEntries) {
  332. result = SetupGetStringField(&infContext, srcFieldOfs, retBuf, retBufSize,
  333. requiredSize);
  334. }
  335. }
  336. //
  337. // Close the INF.
  338. //
  339. if (inf != INVALID_HANDLE_VALUE) {
  340. SetupCloseInfFile(inf);
  341. }
  342. //
  343. // Log an error if there was a real problem.
  344. //
  345. if (!result && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
  346. ASSERT((sizeof(parms)/sizeof(WCHAR *)) >= 1);
  347. parms[0] = (WCHAR *)infName;
  348. TsLogError(EVENT_NOTIFY_ERRORPARSINGINF, EVENTLOG_ERROR_TYPE,
  349. 1, parms, __LINE__);
  350. }
  351. DBGMSG(DBG_ERROR, ("RDPPRUTL:Finished RDPDRUTL_MapPrintDriverName.\n"));
  352. return result && !outOfEntries;
  353. }
  354. PACL
  355. GiveLoggedOnUserFullPrinterAccess(
  356. IN LPTSTR printerName,
  357. IN HANDLE hTokenForLoggedOnUser,
  358. PSECURITY_DESCRIPTOR *ppsd
  359. )
  360. /*++
  361. Routine Description:
  362. Give the logged on user full privilege to manage the specified
  363. printer. The original DACL is returned on success. It can be
  364. used to restore the security settings to what they were prior to
  365. calling this function.
  366. When the caller is done with the returned PSD, it should be freed
  367. using LocalFree. Don't free DACL, it is contained in PSD.
  368. Arguments:
  369. printerName - The name of the relevant printer.
  370. hTokenForLoggedOnUser - Token for logged on user.
  371. ppsd - Pointer to the return security descriptor
  372. parameter.
  373. Return Value:
  374. NULL on error. Otherwise, a pointer to the original DACL is
  375. returned.
  376. --*/
  377. {
  378. PACL pOldDacl = NULL;
  379. PACL pNewDacl = NULL;
  380. ULONG dwResult;
  381. PSID psidUser = NULL;
  382. DWORD dwDaclLength;
  383. DWORD index;
  384. ACCESS_ALLOWED_ACE *pDaclAce;
  385. PSECURITY_DESCRIPTOR psd = NULL;
  386. SECURITY_DESCRIPTOR_CONTROL sdcSDControl;
  387. DWORD dwSDRevision;
  388. PSID psidEveryone = NULL;
  389. SID_IDENTIFIER_AUTHORITY sidEveryoneAuthority = SECURITY_WORLD_SID_AUTHORITY;
  390. WCHAR *eventLogParam;
  391. DBGMSG(DBG_INFO, ("UMRDPPRN:GiveLoggedOnUserFullPrinterAccess entered.\n"));
  392. //
  393. // Get the Security descriptor for the printer
  394. //
  395. dwResult = GetNamedSecurityInfoW(
  396. (LPTSTR)printerName, //Object Name
  397. SE_PRINTER, //Object Type
  398. DACL_SECURITY_INFORMATION, //Security Information to retrieve
  399. NULL, //ppsidOwner
  400. NULL, //ppsidGroup
  401. &pOldDacl, //pointer to Dacl
  402. NULL, //pointer to Sacl
  403. &psd //pointer to Security Descriptor
  404. );
  405. //
  406. // NULL is a valid return value for a Dacl from GetNamedSecurityInfo, but
  407. // is not valid for a printer.
  408. //
  409. if ((dwResult == ERROR_SUCCESS) && (pOldDacl == NULL)) {
  410. DBGMSG(DBG_ERROR, ("UMRDPPRN: NULL Dacl.\n"));
  411. dwResult = ERROR_INVALID_ACL;
  412. ASSERT(FALSE);
  413. }
  414. //
  415. // Get the SID for the logged on user.
  416. //
  417. if (dwResult == ERROR_SUCCESS) {
  418. ASSERT(IsValidAcl(pOldDacl));
  419. if ((psidUser = TSNUTL_GetUserSid(hTokenForLoggedOnUser)) == NULL) {
  420. dwResult = GetLastError();
  421. DBGMSG(DBG_ERROR, ("UMRDPPRN: Failed to get user SID: %ld\n",
  422. dwResult));
  423. }
  424. }
  425. //
  426. // Get the SID for the "Everyone" group.
  427. //
  428. if (dwResult == ERROR_SUCCESS) {
  429. if (!AllocateAndInitializeSid (
  430. &sidEveryoneAuthority, // pIdentifierAuthority
  431. 1, // count of subauthorities
  432. SECURITY_WORLD_RID, // subauthority 0
  433. 0, 0, 0, 0, 0, 0, 0, // subauthorities n
  434. &psidEveryone)) { // pointer to pointer to SID
  435. dwResult = GetLastError();
  436. DBGMSG(DBG_ERROR,
  437. ("UMRDPDR:AllocateAndInitializeSid Failed for Everyone, Error: %ld\n",
  438. dwResult));
  439. }
  440. }
  441. //
  442. // Get SD control bits
  443. //
  444. if (dwResult == ERROR_SUCCESS) {
  445. if (!GetSecurityDescriptorControl(
  446. psd,
  447. (PSECURITY_DESCRIPTOR_CONTROL)&sdcSDControl,
  448. (LPDWORD) &dwSDRevision
  449. )) {
  450. dwResult = GetLastError();
  451. DBGMSG(DBG_ERROR,
  452. ("UMRDPDR:GetSecurityDescriptorControl %ld\n", dwResult));
  453. }
  454. }
  455. //
  456. // Calculate the size of the new ACL.
  457. //
  458. if (dwResult == ERROR_SUCCESS) {
  459. dwDaclLength = sizeof(ACL);
  460. // For logged on user ACE, first set of permissions.
  461. dwDaclLength += (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
  462. GetLengthSid(psidUser);
  463. // For logged on user ACE, second set of permissions.
  464. dwDaclLength += (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
  465. GetLengthSid(psidUser);
  466. // Add some room for existing entries.
  467. if (SE_DACL_PRESENT & sdcSDControl) {
  468. dwDaclLength += pOldDacl->AclSize;
  469. }
  470. }
  471. //
  472. // Create the new DACL.
  473. //
  474. if (dwResult == ERROR_SUCCESS) {
  475. pNewDacl = (PACL)LocalAlloc(LMEM_FIXED, dwDaclLength);
  476. if (pNewDacl == NULL) {
  477. DBGMSG(DBG_ERROR, ("UMRDPPRN:Failed to allocate new ACL.\n"));
  478. dwResult = ERROR_INSUFFICIENT_BUFFER;
  479. }
  480. }
  481. //
  482. // Initialize it.
  483. //
  484. if (dwResult == ERROR_SUCCESS) {
  485. if (!InitializeAcl(pNewDacl, dwDaclLength, ACL_REVISION)) {
  486. dwResult = GetLastError();
  487. DBGMSG(DBG_ERROR, ("UMRDPPRN:InitializeAcl: %ld\n", dwResult));
  488. }
  489. }
  490. //
  491. // Copy the ACE's from the old DACL to the new one.
  492. //
  493. for (index = 0; (dwResult == ERROR_SUCCESS) &&
  494. (index < pOldDacl->AceCount); index++) {
  495. if (!GetAce(pOldDacl, index, (LPVOID *)&pDaclAce)) {
  496. dwResult = GetLastError();
  497. DBGMSG(DBG_ERROR, ("UMRDPPRN:GetAce Failed, Error: %ld\n", dwResult));
  498. }
  499. else {
  500. //
  501. // Copy the ACE if it is not for "Everyone" because the "Everyone"
  502. // group denies us access.
  503. //
  504. if (!EqualSid((PSID) &(pDaclAce->SidStart), psidEveryone)) {
  505. //
  506. // If it's a deny access ACE.
  507. //
  508. if (pDaclAce->Header.AceType == ACCESS_DENIED_ACE_TYPE ||
  509. pDaclAce->Header.AceType == ACCESS_DENIED_OBJECT_ACE_TYPE) {
  510. if (!AddAccessDeniedAce(
  511. pNewDacl, ACL_REVISION, pDaclAce->Mask,
  512. (PSID)&(pDaclAce->SidStart))
  513. ) {
  514. dwResult = GetLastError();
  515. DBGMSG(DBG_ERROR,
  516. ("UMRDPPRN:AddAccessDeniedAce Failed, Error: %ld\n", dwResult));
  517. }
  518. }
  519. //
  520. // Otherwise, it's an add access ACE.
  521. //
  522. else {
  523. if (!AddAccessAllowedAce(
  524. pNewDacl,
  525. ACL_REVISION,
  526. pDaclAce->Mask,
  527. (PSID)&(pDaclAce->SidStart))) {
  528. dwResult = GetLastError();
  529. DBGMSG(DBG_ERROR,
  530. ("UMRDPPRN:AddAccessAllowedAce Failed, Error: %ld\n", dwResult));
  531. }
  532. }
  533. }
  534. }
  535. }
  536. //
  537. // Give the user full privilege
  538. //
  539. if (dwResult == ERROR_SUCCESS) {
  540. if ( ! AddAccessAllowedAce (
  541. pNewDacl,
  542. ACL_REVISION,
  543. PRINTER_READ | PRINTER_WRITE | PRINTER_EXECUTE
  544. | PRINTER_ALL_ACCESS,
  545. psidUser) ) {
  546. dwResult = GetLastError();
  547. DBGMSG(DBG_ERROR,
  548. ("UMRDPDR:AddAccessAllowedAce Failed for Current User, Error: %ld\n",
  549. dwResult));
  550. }
  551. if ( ! AddAccessAllowedAceEx (
  552. pNewDacl,
  553. ACL_REVISION,
  554. OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE,
  555. JOB_ALL_ACCESS | GENERIC_ALL,
  556. psidUser) ) {
  557. dwResult = GetLastError();
  558. DBGMSG(DBG_ERROR,
  559. ("UMRDPDR:AddAccessAllowedAce Failed for Current User, Error: %ld\n",
  560. dwResult));
  561. }
  562. //
  563. // Check the integrity of the new DACL.
  564. //
  565. ASSERT(IsValidAcl(pNewDacl));
  566. }
  567. //
  568. // Add the new settings to the printer.
  569. //
  570. if (dwResult == ERROR_SUCCESS) {
  571. dwResult = SetNamedSecurityInfoW(
  572. (LPTSTR)printerName, //Object Name
  573. SE_PRINTER, //Object Type
  574. DACL_SECURITY_INFORMATION, //Security Information to set
  575. NULL, //psidOwner
  576. NULL, //psidGroup
  577. pNewDacl, //pDacl
  578. NULL //pSacl
  579. );
  580. if (dwResult != ERROR_SUCCESS) {
  581. DBGMSG(DBG_ERROR, ("UMRDPPRN:SetNamedSecurityInfoW returned %ld\n",
  582. dwResult));
  583. }
  584. }
  585. //
  586. // Log an event if this function failed.
  587. //
  588. if (dwResult != ERROR_SUCCESS) {
  589. eventLogParam = printerName;
  590. DBGMSG(DBG_ERROR,
  591. ("UMRDPDR:GiveLoggedOnUserFullPrinterAccess failed with Error Code: %ld.\n",
  592. dwResult));
  593. SetLastError(dwResult);
  594. TsLogError(EVENT_NOTIFY_SET_PRINTER_ACL_FAILED,
  595. EVENTLOG_ERROR_TYPE,
  596. 1,
  597. &eventLogParam,
  598. __LINE__);
  599. //
  600. // Release the security descriptor. This effectively releases the Dacl returned
  601. // by GetNamedSecurityInfo.
  602. //
  603. if (psd) LocalFree(psd);
  604. //
  605. // return NULL values when unsuccessful.
  606. //
  607. pOldDacl = NULL;
  608. psd = NULL;
  609. }
  610. //
  611. // Clean up and return.
  612. //
  613. if (pNewDacl) LocalFree(pNewDacl);
  614. if (psidUser) LocalFree(psidUser);
  615. if (psidEveryone) FreeSid(psidEveryone);
  616. //
  617. // set return parameter.
  618. //
  619. ASSERT( ppsd != NULL );
  620. if( ppsd ) *ppsd = psd;
  621. DBGMSG(DBG_INFO, ("UMRDPPRN:GiveLoggedOnUserFullPrinterAccess done.\n"));
  622. return pOldDacl;
  623. }
  624. DWORD
  625. SetPrinterDACL(
  626. IN LPTSTR printerName,
  627. IN PACL pDacl
  628. )
  629. /*++
  630. Routine Description:
  631. Set the current security settings for a printer to the specified
  632. DACL.
  633. Arguments:
  634. printerName - The name of the relevant printer.
  635. pDacl - The DACL. This function does not free the memory
  636. associated with this data structure.
  637. Return Value:
  638. ERROR_SUCCESS on success. Windows error code is returned otherwise.
  639. --*/
  640. {
  641. DWORD dwResult;
  642. DBGMSG(DBG_TRACE, ("UMRDPDR:SetPrinterDACL entered\n"));
  643. dwResult = SetNamedSecurityInfoW(
  644. (LPTSTR)printerName, //Object Name
  645. SE_PRINTER, //Object Type
  646. DACL_SECURITY_INFORMATION, //Security Information to set
  647. NULL, //psidOwner
  648. NULL, //psidGroup
  649. pDacl, //pDacl
  650. NULL //pSacl
  651. );
  652. if (dwResult != ERROR_SUCCESS) {
  653. DBGMSG(DBG_ERROR, ("UMRDPPRN:SetNamedSecurityInfoW returned %ld\n",
  654. dwResult));
  655. }
  656. DBGMSG(DBG_TRACE, ("UMRDPDR:SetPrinterDACL done\n"));
  657. return dwResult;
  658. }
  659. PSECURITY_DESCRIPTOR
  660. RDPDRUTL_CreateDefaultPrinterSecuritySD(
  661. IN PSID userSid
  662. )
  663. {
  664. /*++
  665. Routine Description:
  666. Return a new default printer security descriptor. The default
  667. settings are:
  668. 1. Administrators: All privileges
  669. 2. Current Logon user: Manager personal preferences and printing only.
  670. 3. Creator_Owner: This function adds document management privilege
  671. 4. Everyone: Permission for the "Everyone" group is completely removed.
  672. Arguments:
  673. userSid - SID, identifying the current TS session/user.
  674. Return Value:
  675. A valid security desriptor or NULL on error. The caller should release
  676. the returned security descriptor and its contained Dacl in a single call
  677. to LocalFree.
  678. GetLastError can be used to retrieve the error status on error.
  679. --*/
  680. PACL pNewDacl = NULL;
  681. PSID psidAdmin = NULL;
  682. PSID psidCreatorOwner = NULL;
  683. PSID psidPowerUser = NULL;
  684. DWORD len;
  685. PBYTE sdBuf;
  686. DWORD dwSDRevision;
  687. DWORD dwDaclLength;
  688. DWORD dwReturnValue = ERROR_SUCCESS;
  689. PSECURITY_DESCRIPTOR psd = NULL;
  690. SID_IDENTIFIER_AUTHORITY sidNTAuthority = SECURITY_NT_AUTHORITY;
  691. SID_IDENTIFIER_AUTHORITY sidCreatorOwnerAuthority = SECURITY_CREATOR_SID_AUTHORITY;
  692. ACCESS_ALLOWED_ACE *pDaclAce;
  693. DWORD index; //for use in a for loop
  694. DWORD dwResult;
  695. DBGMSG(DBG_TRACE, ("UMRDPDR:RDPDRUTL_CreateDefaultPrinterSecuritySD entered\n"));
  696. //
  697. // Get SID of Administrators
  698. //
  699. if (!AllocateAndInitializeSid (
  700. &sidNTAuthority, // pIdentifierAuthority
  701. 2, // count of subauthorities
  702. SECURITY_BUILTIN_DOMAIN_RID, // subauthority 0
  703. DOMAIN_ALIAS_RID_ADMINS, // subauthority 1
  704. 0, 0, 0, 0, 0, 0, // subauthorities n
  705. &psidAdmin)) { // pointer to pointer to SID
  706. dwReturnValue = GetLastError();
  707. DBGMSG(DBG_ERROR,
  708. ("UMRDPDR:AllocateAndInitializeSid Failed for Admin, Error: %ld\n",
  709. dwReturnValue ));
  710. goto CLEANUPANDEXIT;
  711. }
  712. //
  713. // Get SID of CreatorOwner
  714. //
  715. if (!AllocateAndInitializeSid (
  716. &sidCreatorOwnerAuthority, // pIdentifierAuthority
  717. 1, // count of subauthorities
  718. SECURITY_CREATOR_OWNER_RID, // subauthority 0
  719. 0, 0, 0, 0, 0, 0, 0, // subauthorities n
  720. &psidCreatorOwner)) { // pointer to pointer to SID
  721. dwReturnValue = GetLastError();
  722. DBGMSG(DBG_ERROR,
  723. ("UMRDPDR:AllocateAndInitializeSid Failed for CreatorOwner, Error: %ld\n",
  724. GetLastError() ));
  725. goto CLEANUPANDEXIT;
  726. }
  727. //
  728. // Get SID of Power Users
  729. //
  730. if (!AllocateAndInitializeSid (
  731. &sidNTAuthority, // pIdentifierAuthority
  732. 2, // count of subauthorities
  733. SECURITY_BUILTIN_DOMAIN_RID, // subauthority 0
  734. DOMAIN_ALIAS_RID_POWER_USERS, // subauthority 1
  735. 0, 0, 0, 0, 0, 0, // subauthorities n
  736. &psidPowerUser)) { // pointer to pointer to SID
  737. dwReturnValue = GetLastError();
  738. DBGMSG(DBG_ERROR,
  739. ("UMRDPDR:AllocateAndInitializeSid Failed for Power User, Error: %ld\n",
  740. dwReturnValue ));
  741. goto CLEANUPANDEXIT;
  742. }
  743. //
  744. // Get size of memory needed for new DACL
  745. //
  746. dwDaclLength = sizeof(ACL);
  747. dwDaclLength += 2* (sizeof(ACCESS_ALLOWED_ACE) -
  748. sizeof (DWORD) + GetLengthSid(psidAdmin)); //For Admin ACE
  749. dwDaclLength += 3 * (sizeof(ACCESS_ALLOWED_ACE) -
  750. sizeof (DWORD) + GetLengthSid(userSid)); //For Session/User ACE
  751. dwDaclLength += 2* (sizeof(ACCESS_ALLOWED_ACE) -
  752. sizeof (DWORD) + GetLengthSid(psidCreatorOwner)); //For Creator_Owner ACE
  753. dwDaclLength += 2* (sizeof(ACCESS_ALLOWED_ACE) -
  754. sizeof (DWORD) + GetLengthSid(psidPowerUser)); //For PowerUser ACE
  755. //
  756. // Allocate the new security descriptor and the dacl in one chunk.
  757. //
  758. sdBuf = LocalAlloc(LMEM_FIXED, sizeof(SECURITY_DESCRIPTOR) + dwDaclLength);
  759. if (sdBuf == NULL) {
  760. DBGMSG(DBG_ERROR, ("LocalAlloc failed.\n"));
  761. dwReturnValue = ERROR_OUTOFMEMORY;
  762. goto CLEANUPANDEXIT;
  763. }
  764. //
  765. // Initialize the security descriptor.
  766. //
  767. psd = (PSECURITY_DESCRIPTOR)sdBuf;
  768. if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION)) {
  769. DBGMSG(DBG_ERROR, ("InitializeSecurityDescriptor failed.\n"));
  770. dwReturnValue = GetLastError();
  771. goto CLEANUPANDEXIT;
  772. }
  773. //
  774. // Init new DACL
  775. //
  776. pNewDacl = (PACL)(sdBuf + sizeof(SECURITY_DESCRIPTOR));
  777. if (!InitializeAcl(pNewDacl, dwDaclLength, ACL_REVISION)) {
  778. dwReturnValue = GetLastError();
  779. DBGMSG(DBG_ERROR, ("UMRDPDR:InitializeAcl Failed, Error: %ld\n", dwReturnValue));
  780. goto CLEANUPANDEXIT;
  781. }
  782. //
  783. // We will add an ACL with permissions to Admin, Power User, and Current User
  784. //
  785. if (!AddAccessAllowedAceEx(
  786. pNewDacl,
  787. ACL_REVISION,
  788. INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE,
  789. JOB_ALL_ACCESS,
  790. psidAdmin) ||
  791. !AddAccessAllowedAceEx(
  792. pNewDacl,
  793. ACL_REVISION,
  794. 0,
  795. PRINTER_ALL_ACCESS,
  796. psidAdmin) ||
  797. !AddAccessAllowedAceEx(
  798. pNewDacl,
  799. ACL_REVISION,
  800. INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE,
  801. READ_CONTROL,
  802. psidCreatorOwner) || // S-1-3-0
  803. !AddAccessAllowedAceEx(
  804. pNewDacl,
  805. ACL_REVISION,
  806. INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE,
  807. JOB_ALL_ACCESS,
  808. psidCreatorOwner) || // s-1-3-0
  809. !AddAccessAllowedAceEx(
  810. pNewDacl,
  811. ACL_REVISION,
  812. INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE,
  813. JOB_ALL_ACCESS,
  814. psidPowerUser) ||
  815. !AddAccessAllowedAceEx(
  816. pNewDacl,
  817. ACL_REVISION,
  818. 0,
  819. PRINTER_ALL_ACCESS,
  820. psidPowerUser) ||
  821. !AddAccessAllowedAceEx (
  822. pNewDacl,
  823. ACL_REVISION,
  824. 0,
  825. PRINTER_READ,
  826. userSid) ||
  827. !AddAccessAllowedAceEx (
  828. pNewDacl,
  829. ACL_REVISION,
  830. INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE,
  831. READ_CONTROL,
  832. userSid) ||
  833. !AddAccessAllowedAceEx (
  834. pNewDacl,
  835. ACL_REVISION,
  836. INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE,
  837. JOB_ALL_ACCESS,
  838. userSid)) {
  839. dwReturnValue = GetLastError();
  840. DBGMSG(DBG_ERROR, ("UMRDPDR:AddAccessAllowedAceEx returned False: %ld\n", dwReturnValue));
  841. goto CLEANUPANDEXIT;
  842. }
  843. //
  844. // Check if everything went ok
  845. //
  846. if (!IsValidAcl(pNewDacl)) {
  847. dwReturnValue = STATUS_INVALID_ACL;
  848. DBGMSG(DBG_ERROR, ("UMRDPDR:IsValidAcl returned False: %ld\n", dwReturnValue));
  849. goto CLEANUPANDEXIT;
  850. }
  851. //
  852. // Set the Dacl for the SD.
  853. //
  854. if (!SetSecurityDescriptorDacl(psd,
  855. TRUE,
  856. pNewDacl,
  857. FALSE)) {
  858. dwReturnValue = GetLastError();
  859. DBGMSG(DBG_ERROR, ("UMRDPDR:Could not set security info for printer : %ld\n",
  860. dwReturnValue));
  861. }
  862. CLEANUPANDEXIT:
  863. //
  864. // Log an event if this function failed.
  865. //
  866. if (dwReturnValue != ERROR_SUCCESS) {
  867. DBGMSG(DBG_ERROR,
  868. ("UMRDPDR:RDPDRUTL_CreateDefaultPrinterSecuritySD failed with Error Code: %ld.\n",
  869. dwReturnValue));
  870. SetLastError(dwReturnValue);
  871. }
  872. if (psidAdmin) {
  873. FreeSid(psidAdmin);
  874. }
  875. if (psidCreatorOwner) {
  876. FreeSid(psidCreatorOwner);
  877. }
  878. if (psidPowerUser) {
  879. FreeSid(psidPowerUser);
  880. }
  881. //
  882. // Release the SD on failure.
  883. //
  884. if (dwReturnValue != ERROR_SUCCESS) {
  885. LocalFree(psd);
  886. psd = NULL;
  887. }
  888. SetLastError(dwReturnValue);
  889. return psd;
  890. }
  891. DWORD
  892. RDPDRUTL_RemoveAllTSPrinters()
  893. /*++
  894. Routine Description:
  895. Remove all TS printers on the system.
  896. Arguments:
  897. Return Value:
  898. ERROR_SUCCESS if successful. Otherwise, an error code is returned.
  899. --*/
  900. {
  901. PRINTER_INFO_5 *pPrinterInfo = NULL;
  902. DWORD cbBuf = 0;
  903. DWORD cReturnedStructs = 0;
  904. DWORD tsPrintQueueFlags;
  905. NTSTATUS status;
  906. PBYTE buf = NULL;
  907. unsigned char stackBuf[4 * 1024]; // Initial EnumPrinter buffer size to
  908. // avoid two round-trip RPC's, if possible.
  909. //
  910. // Try to enumerate printers using the stack buffer, first, to avoid two
  911. // round-trip RPC's to the spooler, if possible.
  912. //
  913. if (!EnumPrinters(
  914. PRINTER_ENUM_LOCAL, // Flags
  915. NULL, // Name
  916. 5, // Print Info Type
  917. stackBuf, // buffer
  918. sizeof(stackBuf), // Size of buffer
  919. &cbBuf, // Required
  920. &cReturnedStructs)) {
  921. status = GetLastError();
  922. //
  923. // See if we need to allocate more room for the printer information.
  924. //
  925. if (status == ERROR_INSUFFICIENT_BUFFER) {
  926. buf = LocalAlloc(LMEM_FIXED, cbBuf);
  927. if (buf == NULL) {
  928. DBGMSG(DBG_ERROR, ("RDPPNUTL: ALLOCMEM failed. Error: %08X.\n",
  929. GetLastError()));
  930. status = ERROR_OUTOFMEMORY;
  931. }
  932. else {
  933. pPrinterInfo = (PRINTER_INFO_5 *)buf;
  934. status = ERROR_SUCCESS;
  935. }
  936. //
  937. // Enumerate printers.
  938. //
  939. if (status == ERROR_SUCCESS) {
  940. if (!EnumPrinters(
  941. PRINTER_ENUM_LOCAL,
  942. NULL,
  943. 5,
  944. (PBYTE)pPrinterInfo,
  945. cbBuf,
  946. &cbBuf,
  947. &cReturnedStructs)) {
  948. DBGMSG(DBG_ERROR, ("RDPPNUTL: EnumPrinters failed. Error: %08X.\n",
  949. GetLastError()));
  950. status = GetLastError();
  951. }
  952. else {
  953. DBGMSG(DBG_INFO, ("RDPPNUTL: Second EnumPrinters succeeded.\n"));
  954. }
  955. }
  956. }
  957. else {
  958. DBGMSG(DBG_ERROR, ("RDPPNUTL: EnumPrinters failed. Error: %08X.\n",
  959. GetLastError()));
  960. }
  961. }
  962. else {
  963. DBGMSG(DBG_ERROR, ("RDPPNUTL: First EnumPrinters succeeded.\n"));
  964. status = ERROR_SUCCESS;
  965. pPrinterInfo = (PRINTER_INFO_5 *)stackBuf;
  966. }
  967. //
  968. // Delete all the TS printers. We allow ERROR_INSUFFICIENT_BUFFER here because
  969. // a second invokation of EnumPrinters may have missed a few last-minute
  970. // printer additions.
  971. //
  972. if (status == ERROR_SUCCESS) {
  973. DeleteTSPrinters(pPrinterInfo, cReturnedStructs);
  974. status = ERROR_SUCCESS;
  975. }
  976. //
  977. // Release the printer info buffer.
  978. //
  979. if (buf != NULL) {
  980. LocalFree(buf);
  981. }
  982. DBGMSG(DBG_TRACE, ("TShrSRV: RDPPNUTL_RemoveAllTSPrinters exit\n"));
  983. return status;
  984. }
  985. void
  986. DeleteTSPrinters(
  987. IN PRINTER_INFO_5 *pPrinterInfo,
  988. IN DWORD count
  989. )
  990. /*++
  991. Routine Description:
  992. Actually performs the printer deletion.
  993. Arguments:
  994. pPrinterInfo - All printer queues on the system.
  995. count - Number of printers in pPrinterInfo
  996. Return Value:
  997. NA
  998. --*/
  999. {
  1000. DWORD i;
  1001. DWORD regValueDataType;
  1002. DWORD sessionID;
  1003. HANDLE hPrinter = NULL;
  1004. DWORD bufSize;
  1005. PRINTER_DEFAULTS defaults = {NULL, NULL, PRINTER_ALL_ACCESS};
  1006. DBGMSG(DBG_TRACE, ("RDPPNUTL: DeleteTSPrinters entry\n"));
  1007. for (i=0; i<count; i++) {
  1008. if (pPrinterInfo[i].pPrinterName) {
  1009. DBGMSG(DBG_TRACE, ("RDPPNUTL: Checking %ws for TS printer status.\n",
  1010. pPrinterInfo[i].pPrinterName));
  1011. //
  1012. // Is this a TS printer?
  1013. //
  1014. if (pPrinterInfo[i].pPortName &&
  1015. (pPrinterInfo[i].pPortName[0] == 'T') &&
  1016. (pPrinterInfo[i].pPortName[1] == 'S') &&
  1017. ISNUM(pPrinterInfo[i].pPortName[2])) {
  1018. DBGMSG(DBG_ERROR, ("RDPPNUTL: %ws is a TS printer.\n",
  1019. pPrinterInfo[i].pPrinterName));
  1020. }
  1021. else {
  1022. continue;
  1023. }
  1024. //
  1025. // Purge and delete the printer.
  1026. //
  1027. if (OpenPrinter(pPrinterInfo[i].pPrinterName, &hPrinter, &defaults)) {
  1028. if (!SetPrinter(hPrinter, 0, NULL, PRINTER_CONTROL_PURGE) ||
  1029. !DeletePrinter(hPrinter)) {
  1030. DBGMSG(DBG_ERROR, ("RDPPNUTL: Error deleting printer %ws.\n",
  1031. pPrinterInfo[i].pPrinterName));
  1032. }
  1033. else {
  1034. DBGMSG(DBG_ERROR, ("RDPPNUTL: Successfully deleted %ws.\n",
  1035. pPrinterInfo[i].pPrinterName));
  1036. }
  1037. ClosePrinter(hPrinter);
  1038. }
  1039. else {
  1040. DBGMSG(DBG_ERROR,
  1041. ("RDPPNUTL: OpenPrinter failed for %ws. Error: %08X.\n",
  1042. pPrinterInfo[i].pPrinterName,
  1043. GetLastError())
  1044. );
  1045. }
  1046. }
  1047. else {
  1048. DBGMSG(DBG_ERROR, ("RDPPNUTL: Printer %ld is NULL\n", i));
  1049. }
  1050. }
  1051. DBGMSG(DBG_TRACE, ("RDPPNUTL: DeleteTSPrinters exit\n"));
  1052. }