No navigation frame on the left?  Click here.

Printer ACLs

 

Writing a new or modified security descriptor to a printer is documented, but the restrictions could be clearer.  In particular, the SetPrinter() API -- my sample uses it at level 3, where it takes only a security descriptor, nothing else -- places a restriction on what it will accept that differs from the way other security APIs work.

To start, you will have to pass an appropriate PRINTER_DEFAULTS structure to OpenPrinter(); the DesiredAccess member of this struct should have the READ_CONTROL and WRITE_DAC bits set (plus WRITE_OWNER if you intend to change the owner).

When you build the new SD for the printer (or change the one you can retrieve with GetPrinter()), you must clear those parts that you are not allowed to set.  For instance, even if you did not ask for WRITE_OWNER access, GetPrinter() will return an SD with the owner SID filled in; but if you pass that SD straight back to SetPrinter(), the function will fail with ERROR_ACCESS_DENIED.

To clear the owner and group SIDs, just pass a NULL PSID to SetSecurityDescriptorOwner() or SetSecurityDescriptorGroup().

To clear the SACL, you must force the SE_SACL_PRESENT bit in the SD's control word to 1; you can do that with SetSecurityDecriptorSacl( psd, FALSE, NULL, FALSE ).  On NT 5 and up, you can also do a SetSecurityDescriptorControl( psd, SE_SACL_PRESENT, 0 ).

The sample code below uses my fksec classes to do all this, because I am basically a lazy person.  However, I do hope that the code is clear enough to show the principle.

printer_sd.cpp, 3 KB