Solved

Using DeviceIOControl

Posted on 1998-08-26
20
285 Views
Last Modified: 2010-04-04
Hi all,

This one is tricky.  We need to know how to use the DeviceIOControl function to retrieve the starting cluster of a file.

We have the procedure working perfectly in MS VC 5, but it will not work in D4.  Here's what we have so far:

const
     VWIN32_DIOC_DOS_IOCTL = 1;

implementation

{$R *.DFM}

function drive_lock(hDevice:HFILE;drive : integer; lock_level : integer; permission : integer):BOOLEAN;
type
   dioc_regs = record
       reg_EBX,
       reg_EDX,
       reg_ECX,
       reg_EAX,
       reg_EDI,
       reg_ESI,
       reg_Flags : Integer;
   end;

var
   regs : ^dioc_regs;
   fResult : boolean;
   cb : DWord;

begin
     GetMem(Regs, SizeOf(regs));
     regs.reg_EAX := $440d;
     regs.reg_EBX := drive or (lock_level shl 8);
     regs.reg_ECX := $084a;
     regs.reg_EDX := permission;
     regs.reg_Flags := $0001;
     fResult := DeviceIOControl(hDevice,
             VWIN32_DIOC_DOS_IOCTL,
             regs,SizeOf(regs),
             regs,SizeOf(regs),
             cb,
             Nil);
     if (not(fResult) or ((regs.reg_Flags and 1)=1)) then
        Result :=  FALSE
     else
        Result := TRUE;
end;

function drive_unlock(hDevice:HFILE;drive : integer):BOOLEAN;
type
   dioc_regs = packed record
       reg_EBX : integer;
       reg_EDX : integer;
       reg_ECX : integer;
       reg_EAX : integer;
       reg_EDI : integer;
       reg_ESI : integer;
       reg_Flags : integer;
   end;

var
   regs : ^dioc_regs;
   fResult : boolean;
   cb : dword;
begin
     Regs := NIL;
     regs.reg_EAX := $440d;
     regs.reg_EBX := drive;
     regs.reg_ECX := $086a;
     regs.reg_Flags := $0001;

     fResult := DeviceIOControl(hDevice,
             VWIN32_DIOC_DOS_IOCTL,
             regs,SizeOf(regs),
             regs,SizeOf(regs),
             cb,
             Nil);
     if (not(fResult) or ((regs.reg_Flags and 1)=1)) then
        result := FALSE
     else
         Result := TRUE;
end;

function get_cluster(hDevice:HFILE;filename : PChar):integer;
type
   dioc_regs = packed record
       reg_EBX : integer;
       reg_EDX : integer;
       reg_ECX : integer;
       reg_EAX : integer;
       reg_EDI : integer;
       reg_ESI : integer;
       reg_Flags : integer;
   end;

var
   regs : ^dioc_regs;
   fResult : boolean;
   cb : dword;
begin
     Regs := NIL;
     GetMem(Regs, SizeOf(Regs));
     regs.reg_EAX := $440d;
     regs.reg_EBX := 0;
     regs.reg_ECX := $0871;
     regs.reg_EDX := DWord(filename);
     regs.reg_Flags := $0001;

     fResult := DeviceIOControl(hDevice,
             VWIN32_DIOC_DOS_IOCTL,
             regs,SizeOf(regs),
             regs,SizeOf(regs),
             cb,
             Nil);
     if (not(fResult) or ((regs.reg_Flags and 1)=1)) then
        Result := 0
     else
        Result := ((regs.reg_EAX and $ffff) or ((regs.reg_EDX and $ffff) shl 16));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
   hDevice : HFILE;
   drive : integer;
   Ps:   Integer;
    P:  PSecurityAttributes;

begin
     drive := 2;
     P := NIL;
     hDevice := CreateFile('\\.\vwin32',
             0,0, P,0,FILE_FLAG_DELETE_ON_CLOSE,0);
     if (not(drive_lock(hDevice,drive,1,1))) then
        ShowMessage('failed lock')
     else begin
        MessageBox(0,'locked','System',0);
        ps := get_cluster(hDevice,'c:\autoexec.bat');
        if (ps = 0) then
               MessageBox(0,'failed to get cluster','System',0)
        else  begin
             //print out the cluster from pos
        end;
        if (not(drive_unlock(hDevice,drive)))then
               MessageBox(0,'failed to unlock','System',0)
        else
               MessageBox(0,'unlocked','System',0);
     end;
     CloseHandle(hDevice);
end;

end.

I dont know if we have done something wrong here or not, but we are just about to give up (hence the large amounts of points).

To do what we want to do, we first need to lock the drive, then retrieve the cluster number, then unlock the drive again.

I really need this answered ASAP.  Any help at all would be greatfully appreciated.

Code or examples can be posted directly to me at stuartj@futureschool.com.au

Many thanks,


Stuart Johnson.

0
Comment
Question by:SJohnson
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
  • 4
  • +3
20 Comments
 
LVL 1

Author Comment

by:SJohnson
ID: 1337859
Oh!!  I should add something to this.  This function DOES work with Delphi.  There is a program called Directory Snoop written by Briggs Softworks (www.briggsoft.com) using Delphi.  He will not give out too much info on how to do this (and rightly so!), so I have to find out through other means.

Stuart.
0
 
LVL 7

Expert Comment

by:BlackMan
ID: 1337860
Be sure that Align Record Fields (Project/Options/Compiler) is unchecked. Otherwise your DIOC_REGS structure might be stored in memory in a way that DeviceIOControl can't recognise..
0
 
LVL 1

Author Comment

by:SJohnson
ID: 1337861
Hi Blackman,

I just tried that, unfortunately it did not work.  I still can not lock the drive.

Thanks for the suggestions though!

Stuart.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 7

Expert Comment

by:BlackMan
ID: 1337862
Is it the Drive_lock procedure that fails?
0
 
LVL 1

Author Comment

by:SJohnson
ID: 1337863
Yep! Certainly is.  The return of fResult (see code) is FALSE.  And the regs.reg_Flags returns 1, so it is failing in both places.

Stu.
0
 
LVL 7

Expert Comment

by:BlackMan
ID: 1337864
Could you give me an example of how you call the drive_lock procedure so I can test it..
0
 
LVL 5

Expert Comment

by:inter
ID: 1337865
Hi there,
I think the problem is with the ID of the DRIVE. The drives starts from 1 so if you want to access something on C you should give
 drive := 3;
please try and report it, though I have only NT OS(so I can not test it)
Regards, Igor
0
 
LVL 7

Expert Comment

by:BlackMan
ID: 1337866
I've just studied the Win32 Help and I think that you have to implement the call in this way (note the @'s):

     fResult := DeviceIOControl(hDevice,
             VWIN32_DIOC_DOS_IOCTL,
             @regs,SizeOf(regs),
             @regs,SizeOf(regs),
             cb,
             Nil);

0
 
LVL 8

Expert Comment

by:ZifNab
ID: 1337867
something stupid ... you know lock only works when there is actually a disk or cd-rom in the drive... as I said, something very stupid but I wanted to let you know. Zif.
0
 
LVL 4

Expert Comment

by:d003303
ID: 1337868
Hi Stuart,
unfortunately I have only NT, so that could will not work. If you have the Platform SDK from MS, you can trace all API calls from the Directory Snoop app with the tool APIMON.EXE. Just select ntdll.dll and kernel32.dll as known DLLs, enable tracing and you get all API calls in a trace file, including ALL PARAMETERS ! I think this would help you quite a bit...
.I love reverse engineering...

Slash/d003303
0
 
LVL 20

Accepted Solution

by:
Madshi earned 400 total points
ID: 1337869
Stuart Johnson,

now it works. I don't know what the problem was. I just copied your sources and "played" a little bit. Perhaps I implemented just the comments of the others. Don't know. Sorry, if it is so.

const
     VWIN32_DIOC_DOS_IOCTL = 1;

function drive_lock(hDevice:HFILE;drive : integer; lock_level : integer; permission : integer):BOOLEAN;
var
   regs    : record
               reg_EBX, reg_EDX, reg_ECX, reg_EAX : DWORD;
               reg_EDI, reg_ESI, reg_Flags        : DWORD;
             end;
   fResult : boolean;
   cb : DWord;

begin
     regs.reg_EAX := $440d;
     regs.reg_EBX := drive or (lock_level shl 8);
     regs.reg_ECX := $084a;
     regs.reg_EDX := permission;
     regs.reg_Flags := $0001;
     fResult := DeviceIOControl(hDevice,
             VWIN32_DIOC_DOS_IOCTL,
             @regs,SizeOf(regs),
             @regs,SizeOf(regs),
             cb,
             Nil);
     if (not(fResult) or ((regs.reg_Flags and 1)=1)) then
        Result :=  FALSE
     else
        Result := TRUE;
end;

function drive_unlock(hDevice:HFILE;drive : integer):BOOLEAN;
var
   regs    : record
               reg_EBX, reg_EDX, reg_ECX, reg_EAX : DWORD;
               reg_EDI, reg_ESI, reg_Flags        : DWORD;
             end;
   fResult : boolean;
   cb : dword;
begin
     regs.reg_EAX := $440d;
     regs.reg_EBX := drive;
     regs.reg_ECX := $086a;
     regs.reg_Flags := $0001;

     fResult := DeviceIOControl(hDevice,
             VWIN32_DIOC_DOS_IOCTL,
             @regs,SizeOf(regs),
             @regs,SizeOf(regs),
             cb,
             Nil);
     if (not(fResult) or ((regs.reg_Flags and 1)=1)) then
        result := FALSE
     else
         Result := TRUE;
end;

function get_cluster(hDevice:HFILE;filename : PChar):integer;
var
     regs    : record
                 reg_EBX, reg_EDX, reg_ECX, reg_EAX : DWORD;
                 reg_EDI, reg_ESI, reg_Flags        : DWORD;
               end;
   fResult : boolean;
   cb : dword;
begin
     regs.reg_EAX := $440d;
     regs.reg_EBX := 0;
     regs.reg_ECX := $0871;
     regs.reg_EDX := DWord(filename);
     regs.reg_Flags := $0001;

     fResult := DeviceIOControl(hDevice,
             VWIN32_DIOC_DOS_IOCTL,
             @regs,SizeOf(regs),
             @regs,SizeOf(regs),
             cb,
             Nil);
     if (not(fResult) or ((regs.reg_Flags and 1)=1)) then
        Result := 0
     else
        Result := ((regs.reg_EAX and $ffff) or ((regs.reg_EDX and $ffff) shl 16));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
   hDevice : HFILE;
   drive : integer;
   Ps:   Integer;
begin
  drive := ord('C')-ord('A')+1;
  hDevice := CreateFile('\\.\vwin32',0,0, nil,0,FILE_FLAG_DELETE_ON_CLOSE,0);
  if (not(drive_lock(hDevice,drive,1,1))) then
     AlertInfo('failed lock')
  else begin
     MessageBox(0,'locked','System',0);
     ps := get_cluster(hDevice,'c:\autoexec.bat');
     if (ps = 0) then
            MessageBox(0,'failed to get cluster','System',0)
     else  begin
          //print out the cluster from pos
     end;
     if (not(drive_unlock(hDevice,drive)))then
            MessageBox(0,'failed to unlock','System',0)
     else
            MessageBox(0,'unlocked','System',0);
  end;
  CloseHandle(hDevice);
end;

end.

Regards, Madshi.
0
 
LVL 7

Expert Comment

by:BlackMan
ID: 1337870
It looks like you just implemented my last comment...
0
 
LVL 5

Expert Comment

by:inter
ID: 1337871
Hey guys
drive := ord('C')-ord('A')+1; = 3 which as I said before!!!!
Cheers ;-) no problem in any case
0
 
LVL 1

Author Comment

by:SJohnson
ID: 1337872
Madshi,

Well done!!  I havent had a look at what you did, but it worked perfectly!  Enjoy your points! :)

Stu.
0
 
LVL 5

Expert Comment

by:inter
ID: 1337873
Just for your information,
what is WRONG IS DRIVE PARAMETER...
so if you want to do it on DRIVE D set drive = 4. In your original code it is 2 which means drive B. All of you please make a note of this there is no magic in that and there is only single faulty line in the original code which is drive = 2(should be drive =3)...
your pal
igor
0
 
LVL 5

Expert Comment

by:inter
ID: 1337874
Sorry @regs should also be canged so BlackMan is also right.
0
 
LVL 1

Author Comment

by:SJohnson
ID: 1337875
Hi Igore,

FYI, I accidently changed the drive from 3 to 2 yesterday before posting.  It had always been set to 3 (C:), therefore it was my mistake.

But something else has changed, it it has fixed what we where doing.  As I said, I didnt have a chance to look through it, but I will early next week.  I think it had something to do with pointer assignments.

Thanks for your input anyway!

Stuart.
0
 
LVL 7

Expert Comment

by:BlackMan
ID: 1337876
Hmm, inter, guess we'll have to stop posting comments, huh? :-)
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1337877
BlackMan, inter,

sorry again, if I only implemented your comments. However, I didn't look at them before I sent my answer.  :-)

Regards, Madshi.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1337878
O.k., that sounds not so nice...
I did look at your comments, but I did not read them in detail. When I found that there was no complete solution, I just compared stu's sources with my own (I'm using DeviceIOControl myself) - not with your comments.
But if you think you deserve some points, too: Just write me how much points you want and I will post a dummy question for you.   :-)

Madshi.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…
Suggested Courses
Course of the Month11 days, 17 hours left to enroll

623 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question