Link to home
Start Free TrialLog in
Avatar of pr2501
pr2501

asked on

I have to impersonate call to log on when diferent user is on.

Below is a code to test if i can open specific document made by another user.
I have made test on my home pc  and i have got:
'not impersonated call failed, this is good.'

But then problems came because of:
if LogonUser('aaaabc','abbbbc', 'abcccc1000', LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, h)

And  because now on my pc i have set just Login, and there is no need for password, i just type "enter" for any user.
So i have to enable all settings of log on window as below:

Login:

Password:

Log on to:

a si have it in office .

My app is a tool for archiving of some data in specific file directly from machine. This file will be locked in windows for all users except one. And my app will also use this user account.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons;

type
  TForm1 = class(TForm)
    SpeedButton1: TSpeedButton;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var h:cardinal;
    s:string;
    d:cardinal;
begin
  try with tfilestream.create('c:\testdir2\test.txt', fmcreate) do
    try
    finally
      free;
    end;
    showmessage('not impersonated call succeeded. THIS IS BAD.');
  except
    showmessage('not impersonated call failed, this is good.');
  end;
  //////////////
  if LogonUser('aaaabc','abbbbc', 'abcccc1000', LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, h) then  begin
    try
      if ImpersonateLoggedOnUser(h) then   begin
      d:=0;
      GetUserName(nil, d);
      setlength(s, d+1);
      GetUserName(pchar(s), d);
      showmessage('ok: '+s);
           try
           speedbutton1.Font.Color:=clgreen;

              with tfilestream.create('c:\testdir2\test.txt', fmcreate) do
                try
               finally
                free;
                end;
              
               showmessage('Impersonated call succeeded, this is good.');

           except
            showmessage('Impersonated call failed. THIS IS BAD.');
           end;
        end else
        showmessage(syserrormessage(getlasterror));
      finally
       closehandle(h);
     end;
    end else
   showmessage(syserrormessage(getlasterror));
   end;


end.

Open in new window

Avatar of jimyX
jimyX

Sorry not catching you, what you have wrong here? You mean there is an error?
Avatar of pr2501

ASKER

On my pc i have

Login:  ....

Password: (i just click enter)

In log on window when system boots.

But  how to set?

Login:

Password:

Log on to:

Avatar of pr2501

ASKER

So i can test my code above?
You need to adjust some settings in the registry or the Local Security Policy to accept blank passwords.

Just call the following procedure before using LogonUser():

 
Uses Registry;

procedure TForm1.DisableLsa(Disable: Boolean);
var
  MyReg: TRegistry;
begin
  MyReg:=TRegistry.Create;
  try
    MyReg.RootKey:=HKEY_LOCAL_MACHINE;
    MyReg.OpenKey('System\CurrentControlSet\Control\Lsa', true);
    if Disable then
      begin
        MyReg.WriteInteger('LimitBlankPasswordUse',0);
      end
    else
      begin
        MyReg.WriteInteger('LimitBlankPasswordUse',1);
      end;
    MyReg.CloseKey;
  finally
    MyReg.Free;
  end;
end;

Open in new window



DisableLsa(true);
LogonUser(...); // the password parameter to be PChar('') or nil if it is blank

https://www.experts-exchange.com/questions/24133495/LogonUser-problem.html
Avatar of pr2501

ASKER

Sorry , i need window  which has :

Login:

Password:

Log on to:

What do you mean by you want a window?
If you mean you want the user to add the values at the moment of using your application then you can add three edit boxes to your form:

Edit1 is for Username (Login)
Edit2 is for password
Edit3 is for Domain (Log on to):

And in the FormCreate just assign those values to LogonUser(), as follows:

 
Uses Registry;

procedure TForm1.DisableLsa(Disable: Boolean);
var
  MyReg: TRegistry;
begin
  MyReg:=TRegistry.Create;
  try
    MyReg.RootKey:=HKEY_LOCAL_MACHINE;
    MyReg.OpenKey('System\CurrentControlSet\Control\Lsa', true);
    if Disable then
      begin
        MyReg.WriteInteger('LimitBlankPasswordUse',0);
      end
    else
      begin
        MyReg.WriteInteger('LimitBlankPasswordUse',1);
      end;
    MyReg.CloseKey;
  finally
    MyReg.Free;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  h:cardinal;
  User, Pass, Domain : String;
begin
  User := Edit1.text;
  Pass := Edit2.text;
  Domain := Edit3.text;

// if user can not be nil either show error message and exit or accept if it is OK with you
  if User = '' then
    begin
      //showmessage('User can not be empty');
      //exit;
    end;

  DisableLsa(true);

  if LogonUser(Pchar(User),Pchar(Domain), Pchar(Pass), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, h) then
    begin
      try
        if ImpersonateLoggedOnUser(h) then
          begin
            ... // your code goes here
          end;
      finally
       closehandle(h);
     end;
    end
  else
   showmessage(syserrormessage(getlasterror));
end;

Open in new window


If I am away from your point can you explain more please.
Avatar of pr2501

ASKER

Windows start login window must have it.
Avatar of pr2501

ASKER

Thank you.
Which Operating System you are using? if it is Win xp, is it Professional or Home edition?
Do you have a server with domain that you want to join?

You can review the following step-by-step guide on how to join a domain.
http://www.windowsnetworking.com/articles_tutorials/wxpjoind.html

In Win xp home Edition you will not be able to join domain.
Avatar of pr2501

ASKER

II have professional edition.Can i do everything with just one/my PC?
( I have try it. I checked the option to ignore hardware connection, but no success...)
If you do not have a domain you can just use PChar('') as domain parameter, or just put nil, in the LogonUser(). So it becomes:

 
LogonUser(Pchar(User),PChar(''), Pchar(Pass), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, h)

Open in new window


Otherwise you need to turn your PC to a server by having your own domain that others can join requires network knowledge. While it is not required here all you have to do is provide domain if the user is on domain or nil if there is no domain.
Avatar of pr2501

ASKER

I need instructions for:
"Otherwise you need to turn your PC to a server"

I have try with instructions from yours link, which explains how to get to window in attached picture, but i can't do it.


win.JPG
This requires networking knowledge, which at the moment I can not help much with, but I will find out for you.

If I may ask why is that? Because you can write and test your application without domain.
Avatar of pr2501

ASKER

I must log at network with domain.
Avatar of pr2501

ASKER

Real network in office where i work.
I do not think it makes any difference if you finish your code in your own PC having the domain as nil and when you want to move it to a PC that is part of domain you can change it and add that domain. You do not have to have domain at your own PC to get your code working.

i.e.:
In a PC that has no Domain use:
LogonUser(Pchar(User),PChar(''), Pchar(Pass), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, h)

But in a PC that must identify domain use:
LogonUser(Pchar(User),PChar(Domain), Pchar(Pass), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, h)
Avatar of pr2501

ASKER

I have set:
"In a PC that has no Domain use"
and have used

DisableLsa(true);

when i was logged everything was ok but when i logged as other user and started my app

 i have got next message (attached picture);

I have  added TRichedit and TButton to my app. When i click on a button impersonation starts and text from TRichedit has to be copied into C:\testdier\test.txt
The point of my app is to change data in file which i created  when i was logged on that PC.
So then when someone else is logged i can still work with specific file when i use my app.

procedure TForm1.Button1Click(Sender: TObject);
var h:cardinal;
    s:string;
    d:cardinal;

   TextText: textfile;
begin
DisableLsa(true);    //disable password
  try with tfilestream.create('c:\testdir2\test.txt', fmcreate) do
    try
    finally
      free;
    end;
    showmessage('not impersonated call succeeded. THIS IS BAD.');
  except
    showmessage('not impersonated call failed, this is good.');
  end;
  //////////////
  ///

  //  In a PC that has no Domain use:
 if LogonUser(Pchar('aaa'),PChar(''), Pchar(''), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, h)    then begin
    try
      if ImpersonateLoggedOnUser(h) then   begin
      d:=0;
      GetUserName(nil, d);
      setlength(s, d+1);
      GetUserName(pchar(s), d);
      showmessage('ok: '+s);
           try
           speedbutton1.Font.Color:=clgreen;              


              with tfilestream.create('c:\testdir2\test.txt', fmcreate) do
                try

               finally
                free;
                end;
                 
               Richedit1.Lines.SaveToFile('C:\testdir2\test.txt');

               showmessage('Impersonated call succeeded, this is good.');

           except
            showmessage('Impersonated call failed. THIS IS BAD.');
           end;
        end else
        showmessage(syserrormessage(getlasterror));
      finally
       closehandle(h);
     end;
    end else
   showmessage(syserrormessage(getlasterror));
   end;

Open in new window

passw.JPG
>  ...when i logged as other user and started my app

Did you log in with administrator account or limited account?

Users who have limited accounts can not change this property.
Avatar of pr2501

ASKER

Blank password?

Or maybe  should i look to find out how to make users with loggin and  passwords also.

The error "Failed to set data for 'LimitBlankPasswordUse'" occurs because the account type that you used is not Administrator and it does not have privileges to change the Registry and set its values.

Make sure the accounts that you are using are Administrator Accounts.
Avatar of pr2501

ASKER

I have to store data in specific file.

This data can't be accessible to anyone.  But to only specific user: "one".

So i have to create  file as  a user "one". And then to log off. So then when other  user "two" will log on he would not be able to copy or change this data. So data will be protected.
But my app  may impersonate user "one" and store data into specific file when user"two" will be logged on.

If user "two" is administrator he can also change my specific file.  And this a can't allow.
Avatar of pr2501

ASKER

I have also made    user one as administrator.
Avatar of pr2501

ASKER

But still the same message. How can i set use of passwords when i have to log on?
ASKER CERTIFIED SOLUTION
Avatar of jimyX
jimyX

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of pr2501

ASKER

Next code can write to text file just once. Why?
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons,Registry, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    SpeedButton1: TSpeedButton;
    RichEdit1: TRichEdit;
    Button1: TButton;
  
    procedure DisableLsa(Disable: Boolean) ;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
   
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
   DisableLsa(true);    //disable password
end;

procedure TForm1.DisableLsa(Disable: Boolean);
var
  MyReg: TRegistry;
begin
  MyReg:=TRegistry.Create;
  try
    MyReg.RootKey:=HKEY_LOCAL_MACHINE;
    MyReg.OpenKey('System\CurrentControlSet\Control\Lsa', true);
    try
      if Disable then
        begin
          MyReg.WriteInteger('LimitBlankPasswordUse',0);
        end
      else
        begin
          MyReg.WriteInteger('LimitBlankPasswordUse',1);
        end;
    except
      // can not set the registry value
      if MyReg.ReadInteger('LimitBlankPasswordUse') = 1 then
        showmessage('Blank passwords will not be accepted and the Registry can not be changed by the current user to enable that option.');
    end;
    MyReg.CloseKey;
  finally
    MyReg.Free;
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
var h:cardinal;
    s:string;
    d:cardinal;

   TextText: textfile;
begin

  try with tfilestream.create('c:\testdir2\test.txt', fmcreate) do
    try
    finally
      free;
    end;
    showmessage('not impersonated call succeeded. THIS IS BAD.');
  except
    showmessage('not impersonated call failed, this is good.');
  end;
  //////////////
  ///
 // if LogonUser('aaaa','bbbbbbbb', 'ccccccccc', LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, h) then  begin
  //  In a PC that has no Domain use:
 if LogonUser(Pchar('onnnnnnnnnnnn'),PChar(''), Pchar(''), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, h)    then begin
    try
      if ImpersonateLoggedOnUser(h) then   begin
      d:=0;
      GetUserName(nil, d);
      setlength(s, d+1);
      GetUserName(pchar(s), d);
      showmessage('ok: '+s);
           try
           speedbutton1.Font.Color:=clgreen;              


              with tfilestream.create('c:\testdir2\test.txt', fmcreate) do
                try

               finally
                free;
                end;
                 
               Richedit1.Lines.SaveToFile('C:\testdir2\test.txt');

               showmessage('Impersonated call succeeded, this is good.');

           except
            showmessage('Impersonated call failed. THIS IS BAD.');
           end;
        end else
        showmessage(syserrormessage(getlasterror));
      finally
       closehandle(h);
     end;
    end else
   showmessage(syserrormessage(getlasterror));
   end;


end.

Open in new window

What do you mean, is there an error message or it simply does not save after the first time? Because it runs OK in my PC and saves the text from the Richedit to the file whenever the button is clicked.
Avatar of pr2501

ASKER

Here am not logged as administrator.
Today i worked on other things. Thank you for your patience.You are very kind.
I  will continue next year;)

If code is correct. There must be some difficulties about.: how to log?
First as user ?, then as user?.