Re: Network Printing from NT Service
From: Chris Hack (chack_at_xenos.com)
Date: 11/24/03
- Next message: Ignacio Vazquez: "Re: Finding relative path between files"
- Previous message: Rob Kennedy: "Re: Finding relative path between files"
- In reply to: Chris Hack: "Network Printing from NT Service"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Mon, 24 Nov 2003 10:23:32 -0600
Through several days of painstaking research, I finally discovered what I
was missing. I needed to load the profile of the user I was impersonating
so that the network printers would be loaded into the registry hive for that
user (HKEY_USERS). This in turn made the network printers show up in the
Printer.Printers list. Below is some code snipets to reproduce what my code
is now doing and it is working great. Please note that as of Delphi 7, the
API procedures LoadUserProfile and UnloadUserProfile have not been
translated in the Windows.pas unit. I have included the translations for
convenience to others in this post.
TProfileInfo = record
dwSize : DWORD;
dwFlags : DWORD;
lpUserName : LPTSTR;
lpProfilePath : LPTSTR;
lpDefaultPath : LPTSTR;
lpServerName : LPTSTR;
lpPolicyPath : LPTSTR;
hProfile : THandle;
////////////////////////////////////////////////////////////////////////////
///
function LoadUserProfile(
hToken : THandle;
var lpProfileInfo : TProfileInfo
): BOOL; stdcall; external 'userenv.dll' name 'LoadUserProfileA';
////////////////////////////////////////////////////////////////////////////
///
function UnloadUserProfile(
hToken : THandle;
hProfile : THandle
): BOOL ; stdcall; external 'userenv.dll';
////////////////////////////////////////////////////////////////////////////
///
// Logon the user that is to be impersonated
LogonUser(
Username,
Domain,
Password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
UserToken
);
// Must load the users profile before attempting to impersonate to prevent
an access denied error.
FillChar(ProfileInfo, SizeOf(TProfileInfo), #0);
ProfileInfo.dwSize := SizeOf(TProfileInfo);
ProfileInfo.dwFlags := PI_NOUI;
ProfileInfo.lpUserName := PChar(Impersonator.Username);
LoadUserProfile(Result, ProfileInfo);
// Impersonate the user to gain access to network printers connected to the
user
ImpersonateLoggedOnUser(UserToken);
// Refresh the printers so that they are reloaded with the impersonated
users printers
Printer.Refresh;
I have obviously left out all error checking to make the above example more
readable. In a working example you will want to check the return codes of
each API call for errors and put a try finally around the code after
LogonUser to make sure you close the handle to the UserToken. You'll also
need a try finally to make sure UnloadUserProfile is called when you no
longer need the users profile loaded.
I hope this helps someone else avoid the endless hours of research that I
had to go through. This is just my small contribution in return for all the
time that these newsgroups have saved me in the past.
"Chris Hack" <chack@xenos.com> wrote in message
news:3fbd3425$1@newsgroups.borland.com...
> Here is a brief discription of what I'm working with before I ask my
> question.
>
> I have an NT Service application that runs under the local system account.
> The application automates distribution of reports to a recipients printer.
> Each recipient has his/her own printer which is available on the network.
> Since the local system account cannot access network printers, I have
added
> all the individual network printers to an NT User on the machine. Then
from
> the NT Service I Impersonate that NT User to gain access to the printers
> connected to that profile. The problem is, only the local printers show
up
> in the Printer.Printers list.
>
> How do I get access to the network printers?
>
> I have tried WNetAddConnection to establish a connection to a printer and
it
> seems to work, but the printer still does not show up in Printer.Printers.
>
> I have tried AddPrinterConnection2 but I always get Access Denied.
>
> Does anyone have any example of doing this sort of thing?
>
> Please keep in mind that the NT Service is multi-threaded, so several
print
> jobs might be going on at one time. So it would be safer to use existing
> connections than to try and connect a printer to a port on the fly due to
2
> threads possibly trying to add a printer to the same port at the same
time.
>
> Thanks,
> Chris
>
>
- Next message: Ignacio Vazquez: "Re: Finding relative path between files"
- Previous message: Rob Kennedy: "Re: Finding relative path between files"
- In reply to: Chris Hack: "Network Printing from NT Service"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|