Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

456 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993 - 1994.
  5. //
  6. // File: printer.cxx
  7. //
  8. // Contents: local functions
  9. //
  10. // History: 8/94 davemont Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <aclpch.hxx>
  14. #pragma hdrstop
  15. //+---------------------------------------------------------------------------
  16. //
  17. // Function: OpenPrinterObject
  18. //
  19. // Synopsis: Opens the specified printer object
  20. //
  21. // Arguments: [IN pwszPrinter] -- The name of the printer to
  22. // open
  23. // [IN AccessMask] -- Flags indicating if the object
  24. // is to be opened to read or write
  25. // the DACL
  26. // [OUT pHandle] -- Where the open handle is
  27. // returned
  28. //
  29. // Returns: ERROR_SUCCESS -- Success
  30. // ERROR_INVALID_PARAMETER -- A bad name was given
  31. //
  32. //----------------------------------------------------------------------------
  33. DWORD
  34. OpenPrinterObject( IN LPWSTR pwszPrinter,
  35. IN ACCESS_MASK AccessMask,
  36. OUT PHANDLE pHandle)
  37. {
  38. acDebugOut((DEB_TRACE, "in OpenPrinterObject\n"));
  39. DWORD dwErr;
  40. //
  41. // Make sure the printer functions are loaded
  42. //
  43. dwErr = LoadDLLFuncTable();
  44. if(dwErr != ERROR_SUCCESS)
  45. {
  46. return(dwErr);
  47. }
  48. if(pwszPrinter != NULL)
  49. {
  50. PRINTER_DEFAULTS pd;
  51. pd.pDatatype = NULL;
  52. pd.pDevMode = NULL;
  53. pd.DesiredAccess = AccessMask;
  54. //
  55. // open the printer
  56. //
  57. if(DLLFuncs.POpenPrinter(pwszPrinter, pHandle, &pd) == FALSE)
  58. {
  59. dwErr = GetLastError();
  60. }
  61. }
  62. else
  63. {
  64. dwErr = ERROR_INVALID_PARAMETER;
  65. }
  66. acDebugOut((DEB_TRACE, "Out OpenPrinterObject: %lu\n", dwErr));
  67. return(dwErr);
  68. }
  69. //+---------------------------------------------------------------------------
  70. //
  71. // Function: ReadPrinterPropertyRights
  72. //
  73. // Synopsis: Gets the specified security info for the specified printer
  74. // object
  75. //
  76. // Arguments: [IN pwszPrinter] -- The printer to get the rights
  77. // for
  78. // [IN pRightsList] -- SecurityInfo to read based
  79. // on properties
  80. // [IN cRights] -- Number of items in rights list
  81. // [IN AccessList] -- Access List to fill in
  82. //
  83. // Returns: ERROR_SUCCESS -- Success
  84. // ERROR_INVALID_PARAMETER -- A bad property was encountered
  85. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  86. //
  87. //----------------------------------------------------------------------------
  88. DWORD
  89. ReadPrinterPropertyRights(IN LPWSTR pwszPrinter,
  90. IN PACTRL_RIGHTS_INFO pRightsList,
  91. IN ULONG cRights,
  92. IN CAccessList& AccessList)
  93. {
  94. acDebugOut((DEB_TRACE, "in ReadPrinterPropertyRights \n"));
  95. HANDLE hPrinter;
  96. DWORD dwErr;
  97. //
  98. // For the moment, there is only the printer property itself...
  99. //
  100. ASSERT(cRights == 1 && pRightsList[0].pwszProperty == NULL);
  101. if(cRights != 1 || pRightsList[0].pwszProperty != NULL)
  102. {
  103. return(ERROR_INVALID_PARAMETER);
  104. }
  105. dwErr = OpenPrinterObject(pwszPrinter,
  106. GetDesiredAccess(READ_ACCESS_RIGHTS,
  107. pRightsList[0].SeInfo),
  108. &hPrinter);
  109. if(dwErr == ERROR_SUCCESS)
  110. {
  111. dwErr = ReadPrinterRights(hPrinter,
  112. pRightsList,
  113. cRights,
  114. AccessList);
  115. //
  116. // Close the printer handle
  117. //
  118. DLLFuncs.PClosePrinter(hPrinter);
  119. }
  120. acDebugOut((DEB_TRACE, "Out ReadPrinterPropertyRights: %lu\n", dwErr));
  121. return(dwErr);
  122. }
  123. //+---------------------------------------------------------------------------
  124. //
  125. // Function: ReadPrinterRights
  126. //
  127. // Synopsis: Gets the specified security info for the specified printer
  128. // object
  129. //
  130. // Arguments: [IN hPrinter] -- Open printer handle
  131. // [IN pRightsList] -- SecurityInfo to read based
  132. // on properties
  133. // [IN cRights] -- Number of items in rights list
  134. // [IN AccessList] -- Access List to fill in
  135. //
  136. // Returns: ERROR_SUCCESS -- Success
  137. // ERROR_INVALID_PARAMETER -- A bad property was encountered
  138. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  139. //
  140. //----------------------------------------------------------------------------
  141. DWORD
  142. ReadPrinterRights(IN HANDLE hPrinter,
  143. IN PACTRL_RIGHTS_INFO pRightsList,
  144. IN ULONG cRights,
  145. IN CAccessList& AccessList)
  146. {
  147. acDebugOut((DEB_TRACE, "in ReadPrinterRights \n"));
  148. DWORD dwErr = ERROR_SUCCESS;
  149. //
  150. // For the moment, there is only the printer property itself...
  151. //
  152. ASSERT(cRights == 1 && pRightsList[0].pwszProperty == NULL);
  153. if(cRights != 1 || pRightsList[0].pwszProperty != NULL)
  154. {
  155. return(ERROR_INVALID_PARAMETER);
  156. }
  157. UCHAR PI3Buff[PSD_BASE_LENGTH];
  158. PPRINTER_INFO_3 pPI3 = (PPRINTER_INFO_3)PI3Buff;
  159. ULONG cSize = 0;
  160. BOOLEAN fDummy, fParmPresent;
  161. NTSTATUS Status;
  162. PACL pAcl = NULL;
  163. //
  164. // Get printer info 3 (a security descriptor)
  165. //
  166. if(DLLFuncs.PGetPrinter(hPrinter,
  167. 3,
  168. (LPBYTE)pPI3,
  169. PSD_BASE_LENGTH,
  170. &cSize) == FALSE )
  171. {
  172. dwErr = GetLastError();
  173. if(dwErr == ERROR_INSUFFICIENT_BUFFER)
  174. {
  175. //
  176. // Allocate one big enough
  177. //
  178. pPI3 = (PPRINTER_INFO_3)AccAlloc(cSize);
  179. if(pPI3 == NULL)
  180. {
  181. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  182. }
  183. else
  184. {
  185. dwErr = ERROR_SUCCESS;
  186. if(DLLFuncs.PGetPrinter(hPrinter,
  187. 3,
  188. (LPBYTE)pPI3,
  189. cSize,
  190. &cSize) == FALSE)
  191. {
  192. dwErr = GetLastError();
  193. }
  194. }
  195. }
  196. }
  197. //
  198. // Because the printer APIs are not very smart, we need to make
  199. // an explicit check to see if the handle was opened with the correct
  200. // access to return what the caller wants.
  201. //
  202. // eg. if caller wants a DACL but got the handle with only
  203. // ACCESS_SYSTEM_INFO, then we need to return ACCESS_DENIED.
  204. //
  205. if(dwErr == ERROR_SUCCESS)
  206. {
  207. //
  208. // If caller wants DACL, group, or owner, then they must open
  209. // the handle with READ_CONTROL. The only way we can check this
  210. // is to see if there is a DACL present.
  211. //
  212. fParmPresent = FALSE;
  213. Status = RtlGetDaclSecurityDescriptor(pPI3->pSecurityDescriptor,
  214. &fParmPresent,
  215. &pAcl,
  216. &fDummy);
  217. if(NT_SUCCESS(Status))
  218. {
  219. if (fParmPresent == FALSE &&
  220. (FLAG_ON(pRightsList[0].SeInfo,DACL_SECURITY_INFORMATION) ||
  221. FLAG_ON(pRightsList[0].SeInfo,OWNER_SECURITY_INFORMATION)||
  222. FLAG_ON(pRightsList[0].SeInfo,GROUP_SECURITY_INFORMATION)))
  223. {
  224. //
  225. // this means that the handle was not open with correct access.
  226. //
  227. dwErr = ERROR_ACCESS_DENIED;
  228. }
  229. }
  230. else
  231. {
  232. dwErr = RtlNtStatusToDosError(Status);
  233. }
  234. }
  235. if(dwErr == ERROR_SUCCESS)
  236. {
  237. //
  238. // Do same hack with SACL
  239. //
  240. fParmPresent = FALSE;
  241. Status = RtlGetSaclSecurityDescriptor(pPI3->pSecurityDescriptor,
  242. &fParmPresent,
  243. &pAcl,
  244. &fDummy);
  245. if(NT_SUCCESS(Status))
  246. {
  247. if(fParmPresent == FALSE &&
  248. FLAG_ON(pRightsList[0].SeInfo,SACL_SECURITY_INFORMATION))
  249. {
  250. dwErr = ERROR_ACCESS_DENIED;
  251. }
  252. }
  253. else
  254. {
  255. dwErr = RtlNtStatusToDosError(Status);
  256. }
  257. }
  258. //
  259. // Finally, add the security descriptor
  260. //
  261. if(dwErr == ERROR_SUCCESS)
  262. {
  263. dwErr = AccessList.AddSD(pPI3->pSecurityDescriptor,
  264. pRightsList->SeInfo,
  265. pRightsList->pwszProperty);
  266. }
  267. if(cSize > PSD_BASE_LENGTH)
  268. {
  269. AccFree(pPI3);
  270. }
  271. acDebugOut((DEB_TRACE, "Out ReadPrinterRights: %lu\n", dwErr));
  272. return(dwErr);
  273. }
  274. //+---------------------------------------------------------------------------
  275. //
  276. // Function: GetPrinterParentRights
  277. //
  278. // Synopsis: Determines who the parent is, and gets the access rights
  279. // for it. It is used to aid in determining what the approriate
  280. // inheritance bits are.
  281. //
  282. // This operation does not make sense for kernel objects
  283. //
  284. // Arguments: [IN pwszPrinter] -- The printer to get the parent
  285. // for
  286. // [IN pRightsList] -- The properties to get the
  287. // rights for
  288. // [IN cRights] -- Number of items in rights list
  289. // [OUT ppDAcl] -- Where the DACL is returned
  290. // [OUT ppSAcl] -- Where the SACL is returned
  291. // [OUT ppSD] -- Where the Security Descriptor
  292. // is returned
  293. //
  294. // Returns: ERROR_INVALID_FUNCTION -- Call doesn't make sense here
  295. //
  296. //----------------------------------------------------------------------------
  297. DWORD
  298. GetPrinterParentRights(IN LPWSTR pwszPrinter,
  299. IN PACTRL_RIGHTS_INFO pRightsList,
  300. IN ULONG cRights,
  301. OUT PACL *ppDAcl,
  302. OUT PACL *ppSAcl,
  303. OUT PSECURITY_DESCRIPTOR *ppSD)
  304. {
  305. //
  306. // This doesn't currently make sense for kernel objects, so simply
  307. // return an error
  308. //
  309. return(ERROR_INVALID_FUNCTION);
  310. }
  311. //+---------------------------------------------------------------------------
  312. //
  313. // Function: SetPrinterSecurityInfo
  314. //
  315. // Synopsis: Sets the specified security info on the specified printer
  316. // object
  317. //
  318. // Arguments: [IN hPrinter] -- The handle of the object
  319. // [IN SeInfo] -- Flag indicating what security
  320. // info to set
  321. // [IN pwszProperty] -- The property on the object to
  322. // set
  323. // For kernel objects, this MBZ
  324. // [IN pSD] -- The security descriptor to set
  325. //
  326. // Returns: ERROR_SUCCESS -- Success
  327. // ERROR_INVALID_PARAMETER -- A bad property was given
  328. //
  329. //----------------------------------------------------------------------------
  330. DWORD
  331. SetPrinterSecurityInfo(IN HANDLE hPrinter,
  332. IN SECURITY_INFORMATION SeInfo,
  333. IN PWSTR pwszProperty,
  334. IN PSECURITY_DESCRIPTOR pSD)
  335. {
  336. acDebugOut((DEB_TRACE, "in SetPrinterSecurityInfo\n"));
  337. DWORD dwErr = ERROR_SUCCESS;
  338. //
  339. // Make sure the printer functions are loaded
  340. //
  341. dwErr = LoadDLLFuncTable();
  342. if(dwErr != ERROR_SUCCESS)
  343. {
  344. return(dwErr);
  345. }
  346. //
  347. // Service don't have properties
  348. //
  349. if(pwszProperty != NULL)
  350. {
  351. dwErr = ERROR_INVALID_PARAMETER;
  352. }
  353. else
  354. {
  355. PRINTER_INFO_3 PI3;
  356. PI3.pSecurityDescriptor = pSD;
  357. if (DLLFuncs.PSetPrinter(hPrinter,
  358. 3,
  359. (LPBYTE)&PI3,
  360. 0) == FALSE)
  361. {
  362. dwErr = GetLastError();
  363. }
  364. }
  365. acDebugOut((DEB_TRACE, "Out SetPrinterSecurityInfo: %lu\n", dwErr));
  366. return(dwErr);
  367. }
  368. //+---------------------------------------------------------------------------
  369. //
  370. // Function: ClosePrinterObject
  371. //
  372. // Synopsis: Closes the opened printer handle
  373. //
  374. // Arguments: [IN hPrinter] -- The handle of the printer
  375. //
  376. // Returns: ERROR_SUCCESS -- Success
  377. //
  378. //----------------------------------------------------------------------------
  379. DWORD
  380. ClosePrinterObject(IN HANDLE hPrinter)
  381. {
  382. acDebugOut((DEB_TRACE, "in ClosePrinterObject\n"));
  383. DWORD dwErr = ERROR_SUCCESS;
  384. //
  385. // Make sure the printer functions are loaded
  386. //
  387. dwErr = LoadDLLFuncTable();
  388. if(dwErr != ERROR_SUCCESS)
  389. {
  390. return(dwErr);
  391. }
  392. //
  393. // Close the printer handle
  394. //
  395. DLLFuncs.PClosePrinter(hPrinter);
  396. acDebugOut((DEB_TRACE, "Out ClosePrinterObject: %lu\n", dwErr));
  397. return(dwErr);
  398. }