Return values from WinAPI call

This procedure returns false if no diskette is found in drive A, otherwise it returns true. When it returns true I want to retrieve the serial number in the 'result' variable. How could this be done?


procedure GetInfo ;export;
  var
     dwTemp1, dwTemp2 : LongInt;
     Result : DWord;
  begin
     GetVolumeInformation (
        PChar('A:\'),
        Nil,
        0,
        @Result,
        dwTemp1,
        dwTemp2,
        Nil,
        0);
  end;

  exports
     GetInfo;

LVL 1
DiverAsked:
Who is Participating?
 
vladikaCommented:
Ok. You are right. I forget about stdcall
Try this

library mylib;

uses
  Windows,
  SysUtils,
  Classes;

type
  TCompName = array [0..MAX_COMPUTERNAME_LENGTH] of Char;

function GetInfo(var SerialNumber: DWORD): Boolean; stdcall; // use stdcall calling convention
 // use var to export SerialNumber
var
  dwTemp1, dwTemp2 : LongInt;
begin
  Result := GetVolumeInformation('A:\', nil, 0, @SerialNumber,
    dwTemp1, dwTemp2, nil, 0);
end;

function GetCompName(var CompName: TCompName): Boolean; stdcall; // use stdcall
var L: Integer;
begin
  L := SizeOf(CompName);
  Result := GetComputerName(CompName, L); // CompName have MAX_COMPUTERNAME_LENGTH + 1 characters
end;

exports
  GetInfo index 1,
  GetCompName index 2;
 
begin
end.


How to use
type
  TCompName = array [0..MAX_COMPUTERNAME_LENGTH] of Char; // redeclare TCompName since we cannot export type definition

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function GetInfo(var SerialNumber: DWORD): Boolean; stdcall; external 'mylib.dll'; // import GetInfo
function GetCompName(var CompName: TCompName): Boolean; stdcall; external 'mylib.dll'; // import GetCompName

procedure TForm1.Button1Click(Sender: TObject);
var SN: Integer;
    S: string;
begin
  SN := 0;
  if GetInfo(SN) then
  begin
    S := 'Serial Number: ' +
      IntToHex(HiWord(SN), 4) + '-' + IntToHex(LoWord(SN), 4);
    Application.MessageBox(PChar(S), '', 0)
  end else
    Application.MessageBox('Insert disk', 'Error', 0);
end;

procedure TForm1.Button2Click(Sender: TObject);
var CompName: TCompName;
begin
  if GetCompName(CompName) then
    Application.MessageBox(CompName, 'ComputerName', 0)
  else
    Application.MessageBox('Cannot find computer name', 'Error', 0)
end;

0
 
ZifNabCommented:
Hi Diver,

Getting the serial number of a disk.

                         Question:

                         How do I retrieve the serial number of a disk?

                         Answer:

                         You can use the Windows API function GetVolumeInformation()

                         procedure TForm1.Button1Click(Sender: TObject);
                         var
                           VolumeSerialNumber : DWORD;
                           MaximumComponentLength : DWORD;
                           FileSystemFlags : DWORD;
                           SerialNumber : string;
                         begin
                           GetVolumeInformation('C:\',
                                                nil,
                                                0,
                                                @VolumeSerialNumber,
                                                MaximumComponentLength,
                                                FileSystemFlags,
                                                nil,
                                                0);
                           SerialNumber := IntToHex(HiWord(VolumeSerialNumber), 4) +
                                           '-' +
                                           IntToHex(LoWord(VolumeSerialNumber), 4);
                           Memo1.Lines.Add(SerialNumber);
                         end;
(From Borlands developer support)

Regards, ZiF.
0
 
DiverAuthor Commented:
Yes, I know how to retrieve it. But how can it be returned from a function in a dll? I want to return both the value of the GetVolumeInformation function as the serial number in the 4th parameter. That's what I was asking for.
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
vladikaCommented:
function GetInfo(VAR SerialNumber: DWORD): Boolean;
var
  dwTemp1, dwTemp2 : LongInt;
begin
  Result := GetVolumeInformation (
            'A:\', Nil, 0,
            @SerialNumber,
            dwTemp1, dwTemp2, Nil, 0);
end;

0
 
DiverAuthor Commented:
Vladika, I don't think you tested your code. When inserting a disk I get an acces violation error at address...

OK, it looks like it is not that easy... hmm, let me raise the points... hope I get the right answer this time.

I want to use Win API calls like GetVolumeInfo and GetComputerName in functions in a DLL.
So, the result of this function has to be exported.
But, I also want to export the value of certain parameters, like the name of the GetComputerName call and the serial number of the GetVolumeInfo call.

Please provide me with the correct code for BOTH calls. A brief explanation of what exactly is happening would be welcome too. This is new stuff to me and I want to learn something from you.

I hope I made myself clear.
0
 
vladikaCommented:
If something is incomprehensible, ask questions

0
 
DiverAuthor Commented:
Hello, Vladika. This works fine now. Excellent work! Sorry for my nervous reaction yesterday; suppose I was doing to much things at a time. Can I still ask you a few questions? I'll raise the points to 120 to compensate for your effort. BTW, are you Russian or is this just a good sounding nickname :-) ?

How come that the serial number is returned in the 'result' variable and not the boolean output of the GetVolumeInformation itself?

Why has CompName to be defined as an array of char? Can't it be returned as a string?

The GetVolumeInformation function now only reads drive A (hard coded). How would this function be written if the drive letter is an input variable coming from a textbox on a form? (the function is always called from the dll, so the drive letter has to be passed from the form to the dll).

Hope this is a bit clear. Anyway, thanks for helping me that much.
0
 
vladikaCommented:
Hello, Diver.

Yes, I am Russian. I think you guessed by my bad English :)

> How come that the serial number is returned in the 'result' variable and not the boolean
> output of the GetVolumeInformation itself?
> How would this function be written if the drive letter is an input variable coming
> from a textbox on a form?

Here is example
................
function GetInfo2(Drive: PChar): DWORD; stdcall;
var
  dwTemp1, dwTemp2 : LongInt;
begin
  if not GetVolumeInformation(Drive, nil, 0, @Result,
    dwTemp1, dwTemp2, nil, 0) then Result := 0;  // '0' indicates error
end;
................
exports
  GetInfo2 index 3;
................

In the program
...........
function GetInfo2(Drive: PChar): DWORD; stdcall; external 'mylib.dll';
...........
procedure TForm1.Button3Click(Sender: TObject);
var SN: Integer;
    S: string;
begin
  SN := GetInfo2(PChar(Edit1.Text));
  if SN <> 0 then // no error
  begin
    S := 'Serial Number: ' +
      IntToHex(HiWord(SN), 4) + '-' + IntToHex(LoWord(SN), 4);
    Application.MessageBox(PChar(S), '', 0)
  end else
    RaiseLastWin32Error;
end;


> Why has CompName to be defined as an array of char?
array of char is equvalent PChar
You must pass in GetComputerName buffer which
should be large enough to contain MAX_COMPUTERNAME_LENGTH + 1 characters
So, TCompName is
1) PChar
2) have enough size to contain MAX_COMPUTERNAME_LENGTH + 1 characters

> Can't it be returned as a string?
I don't try such thing.
I think the problems appears with using this dll in not Delphi.
Use PChar instead of string.

0
 
DiverAuthor Commented:
Vladika, it was not your English, but your name that made me think you're Russian. BTW, your English is not bad at all (mine is not perfect either, because it's not my native language).
Thanks for answering all my question. Thanks also for the code: this works fine too.
I just want to ask you one more favor (and I'm raising the points again - in fact I'm planning to double them :-) - if you can answer me). I have a homemade C++ dll that reads and writes to sectors on a disk, and sets a volume id. What follows are the declarations in the header file.
Can this dll be called from my dll? Can you do that in Delphi code?

Functions:
----------
ReadFloppySectors(drive, sector, num, buffer)
WriteFloppySectors(drive, sector, num, buffer)
SetVolumeId(drive, id)

Arguments:
----------
drive      - Floppy drive number (0 = "A:", 1 = "B:")
sector      - First sector number
num      - Number of sectors
buffer      - Address of allocated buffer
                    Buffer size must be a multiple of sector size (usually 512 bytes)
id      - A 32-bit hex representation

0
 
vladikaCommented:
Hi, Diver

> Can this dll be called from my dll? Can you do that in Delphi code?
Yes, yes.

But information is not enough.
Before write dll I must know
1) parameters types
2) calling convention
3) procedure import name or index
4) your dll name

You can send me dll and header file by email
demon@dezcom.mephi.ru

Or write here missing information

0
 
DiverAuthor Commented:
Thanks, Dmitri. You've done an excellent job!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.