HOW to use GetDiskSerial.dll in MQL4?

 

I am trying to use GetDiskSerial.dll in mql4 to get HDD serail num.



{*******************************************************}
{                                                       }
{       Borland Delphi Interface Unit                   }
{                                                       }
{       Copyright (c) 2002-2011, Devlib,Inc.            }
{                                                       }
{       http://www.devlib.net                           }
{                                                       }
{*******************************************************}

unit HDiskInfo;

interface

type

  DiskInfo = record
    SerialNumber: array[0..19] of AnsiChar;
    ModelNumber: array[0..39] of AnsiChar;
    FirmwareRev: array[0..8] of AnsiChar;
    InterfaceType: array[0..9] of AnsiChar;
    MediaType: array[0..39] of AnsiChar;
    BufferSize: Longword;
    Cylinders: Longword;
    Heads: Longword;
    Sectors: Longword;
    SectorsPerTrack: Longword;
    BytesPerSector: Longword;
  end;
  PDiskInfo = ^DiskInfo;

  procedure SetLicenseKey(RegCode: PAnsiChar); stdcall; external 'GetDiskSerial.dll';
  function GetDllVer: PAnsiChar; stdcall; external 'GetDiskSerial.dll';
  function GetDriveCount: Byte; stdcall; external 'GetDiskSerial.dll';
  function GetDriveLetter(DriveIndex: Byte): PAnsiChar; stdcall; external 'GetDiskSerial.dll';
  function GetDriveSize(DriveIndex: Byte): PAnsiChar; stdcall; external 'GetDiskSerial.dll';
  function GetDriveInfo(DriveIndex: Byte; var DiskInfo: DiskInfo): LongBool; stdcall; external 'GetDiskSerial.dll';
  function GetSerialNumber(DriveIndex: Byte): PAnsiChar; stdcall; external 'GetDiskSerial.dll';
  function GetModelNumber(DriveIndex: Byte): PAnsiChar; stdcall; external 'GetDiskSerial.dll';
  function GetFirmwareRev(DriveIndex: Byte): PAnsiChar; stdcall; external 'GetDiskSerial.dll';
  function GetInterfaceType(DriveIndex: Byte): PAnsiChar; stdcall; external 'GetDiskSerial.dll';
  function GetMediaType(DriveIndex: Byte): PAnsiChar; stdcall; external 'GetDiskSerial.dll';    
  function GetBufferSize(DriveIndex: Byte): Longword; stdcall; external 'GetDiskSerial.dll';
  function GetCylinders(DriveIndex: Byte): Longword; stdcall; external 'GetDiskSerial.dll';
  function GetHeads(DriveIndex: Byte): Longword; stdcall; external 'GetDiskSerial.dll';
  function GetSectors(DriveIndex: Byte): Longword; stdcall; external 'GetDiskSerial.dll';
  function GetSectorsPerTrack(DriveIndex: Byte): Longword; stdcall; external 'GetDiskSerial.dll';
  function GetBytesPerSector(DriveIndex: Byte): Longword; stdcall; external 'GetDiskSerial.dll';
  function GetDiskVolumeNumber(DriveLetter: PAnsiChar): PAnsiChar; stdcall; external 'GetDiskSerial.dll';

implementation

end.




my code in mt4 like this

#import "GetDiskSerial.dll"
char GetSerialNumber(void);
#import

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
  
   MessageBox(CharToString(GetDriveSize()));

  }

but i got ritical error when I run this script

and error in the log like this

2015.10.19 20:18:58.133    test USDJPY,H1: stack damaged, check DLL function call in 'test.mq4' (30,28)

I know it is the parameter I passed is not good, but I do not know how to make it correct.

anyone know the right way to code this ?














 
A serial number is not going to be a single character, either a array or an int. Your call is bogus.
 

Any way - interesting problem!

I was trying to use kernel32.dll:


..
//+------------------------------------------------------------------+
//|                                     Test_PcValiadtion_VolNum.mq4 |
//|                        Copyright 2014, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

#import "kernel32.dll"
bool GetVolumeInformationW(string drvLetter, string& VolNameBuff[], uint VolumeNameSize, uint& SerialNumber, uint& SerialNumberLength, uint& flags, string& fs[], uint fs_size);
#import
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   string VolNameBuff[261], fs[261],strVNB="",strFS="";
   uint SerialNumber,SerialNumberLength, flags;
   bool ok = GetVolumeInformationW("C:\\", VolNameBuff, 261, SerialNumber,SerialNumberLength, flags, fs, 261);
   for(int i=0;i<250;i++){
      strVNB = strVNB+VolNameBuff[i];
      //CRASH: strFS  = strFS +fs[i]; // <= Access violation read to 0x00530042 in 'C:\Users\cas\Documents\MT4\mt2\MQL4\Scripts\Test_PcValiadtion_VolNum.ex4'
   }
   // serNum: 2465386989, Length 255, flags: 65470719
   Comment("ok:",(string)ok,"\nVNB:",strVNB,"<\nfs:",strFS,"<\nSerNum:",SerialNumber,"\nFlags:",flags);
   DebugBreak();
  }
//+------------------------------------------------------------------+


But, the result buffers are empty and the other values are misleading - I should expect:

HDD

  Partition ID:         004B-4EE8

  Hard drive unique ID:     S1SXNSAF908244V

To get this information by http://www.soft.tahionic.com/download-hdd_id/index.html I have to start this as administrator.

So how do we get the HD-SerialNumber as clients?

 
gooly:

Any way - interesting problem!

I was trying to use kernel32.dll:



But, the result buffers are empty and the other values are misleading - I should expect:

HDD

  Partition ID:         004B-4EE8

  Hard drive unique ID:     S1SXNSAF908244V

To get this information by http://www.soft.tahionic.com/download-hdd_id/index.html I have to start this as administrator.

So how do we get the HD-SerialNumber as client


The function declaration I use (and it works) is

BOOL WINAPI GetVolumeInformationW(
  _In_opt_   LPCTSTR lpRootPathName,
  _Out_opt_  LPTSTR lpVolumeNameBuffer,
  _In_       DWORD nVolumeNameSize,
  _Out_opt_  LPDWORD lpVolumeSerialNumber,
  _Out_opt_  LPDWORD lpMaximumComponentLength,
  _Out_opt_  LPDWORD lpFileSystemFlags,
  _Out_opt_  LPTSTR lpFileSystemNameBuffer,
  _In_       DWORD nFileSystemNameSize
);

 so not sure how you came to those string arrays:

bool GetVolumeInformationW(string drvLetter, string& VolNameBuff[], uint VolumeNameSize, uint& SerialNumber, uint& SerialNumberLength, uint& flags, string& fs[], uint fs_size);
 
Ovo:

The function declaration I use (and it works) is

 so not sure how you came to those string arrays:

Can you provide the mt4-definitions of the variables and the function call?
 
Ovo:
GetVolumeInformationW

What GetVolumeInformationW() returns isn't a proper serial number. It's a value which is easily changed using free utilities if a user realizes that you are using that info for licensing. (I think that we may have had this conversation before...). For example, Microsoft provide such an app themselves: https://technet.microsoft.com/en-gb/sysinternals/bb897436.aspx

I don't know whether http://www.devlib.net/getdiskserial.htm is the "GetDiskSerial.dll" which the OP is trying to use but that, for example, quite specifically and correctly draws the following distinction: "REAL serial number of hard disk. NOT Partition ID, NOT Volume ID !" 

 
jjc:

(I think that we may have had this conversation before...).  

GetVolumeInformationW() is very likely to be good enough for your purposes, as a compromise between ease of use versus security. But it's got big problems if e.g. you are supplying software into an environment where there may be lots of computers cloned from the same disk image, and where you want to be able to license each one individually.
 
jjc:
GetVolumeInformationW() is very likely to be good enough for your purposes, as a compromise between ease of use versus security. But it's got big problems if e.g. you are supplying software into an environment where there may be lots of computers cloned from the same disk image, and where you want to be able to license each one individually.

Currently I have sample of about 5k computers, and the number is really not unique, but in fact it can be used for MQL deployment when combined it with a couple of additional parameters. I encountered very few duplicate numbers in the sample (less than 100)  and only two or three were above five. But the actual problem are Linux and Mac simulators, some have dummy implementation returning zero.

 

 

 

gooly:
Can you provide the mt4-definitions of the variables and the function call?

I have it in other files, so hopefully it is everything:

#define ULONG_PTR DWORD_PTR
#define BYTE uchar
#define LPDWORD DWORD&
#define DWORD uint
#define WORD ushort
#define UINT uint
#define PULONG ULONG&
#define ULONG uint
#define LONG int
#define LONGLONG long
#define SHORT short
#define LPVOID MT4Structure&
#define PVOID uint 
#define DWORD_PTR uint
#define TCHAR ushort
#define _Out_ 
#define _In_ const
#define _Out_opt_ 
#define _Inout_opt_
#define _In_opt_
#define _Inout_
#define WINAPI
#define BOOL bool
#define LPCTSTR string&
#define LPTSTR string&

 

  /**
   * Reads ID of hard drive, where common data folder is
   */
   uint readDrive() {
      TRACEIN_;
      string volumeName, volumeBuffer; // i.e. NULL
      createStringBuffer(volumeName);
      createStringBuffer(volumeBuffer);
      uint serialNumber, dummy1, dummy2;
      
      // get common path drive
      MT4String rootpathString(TerminalInfoString(TERMINAL_COMMONDATA_PATH));
      string rootpath = rootpathString.subString(0, rootpathString.find("\\") + 1);
      GetVolumeInformationW(rootpath, volumeName, StringLen(volumeName), serialNumber, dummy1, dummy2, volumeBuffer, StringLen(volumeBuffer));
      TRACEOUT(serialNumber);
      return serialNumber;
   }
 
I found this: https://www.mql5.com/en/forum/150583 wich gives me the same result: no volume ID, just a number.
 
Carl Schreiber:
I found this: https://www.mql5.com/en/forum/150583 wich gives me the same result: no volume ID, just a number.
#property strict
//---
#import "Kernel32.dll"
bool GetVolumeInformationW(string,string,uint,uint&[],uint,uint,string,uint);
#import
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   Print("VSN: ",VolumeSerialNumber());
//---
  }
//+------------------------------------------------------------------+
//| VolumeSerialNumber                                               |
//+------------------------------------------------------------------+
string VolumeSerialNumber()
  {
//---
   string res="";
//---
   string RootPath=StringSubstr(TerminalInfoString(TERMINAL_COMMONDATA_PATH),0,1)+":\\";
   string VolumeName,SystemName;
   uint VolumeSerialNumber[1],Length=0,Flags=0;
//---
   if(!GetVolumeInformationW(RootPath,VolumeName,StringLen(VolumeName),VolumeSerialNumber,Length,Flags,SystemName,StringLen(SystemName)))
     {
      res="XXXX-XXXX";
      Print("Failed to receive VSN !");
     }
   else
     {
      //--
      uint VSN=VolumeSerialNumber[0];
      //--
      if(VSN==0)
        {
         res="0";
         Print("Error: Receiving VSN may fail on Mac / Linux.");
        }
      else
        {
         res=StringFormat("%X",VSN);
         res=StringSubstr(res,0,4)+"-"+StringSubstr(res,4,8);
         //Print("VSN successfully received.");
        }
      //--
     }
//---
   return(res);
  }
//+------------------------------------------------------------------+
 
GetSystemInfo
Reason: