Protecting programs from piracy

How can I get the hard disk's serial number in order to protect my program from running elsewhere that in that particular hard disk ?
simeAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jackb022197Commented:
See the unit below...

unit SerNum;

Interface

uses WinProcs, WinTypes;

function GetSerialNumber (drive: Byte): LongInt;
function SetSerialNumber (drive: Byte; serNum: LongInt): Bool;

Implementation

type
    PMIDINFO = ^MIDINFO;
    MIDINFO = record
                  InfoLevel:  Word;
                  SerialNum:  Longint;
                  VolLabel:   array[0..10] of Char;
                  FileSystem: array [0..7] of Char;
              end;

var
    R: record     { Real mode call structure }
           di, si, bp, Reserved, bx, dx, cx, ax : Longint;
           Flags, es, ds, fs, gs, ip, sp, ss: Word;
       end;

{----------------------------------------------------------------------------}
{    Name:    GetSetMid                                                      }
{    Purpose: Low level code to get or set a MIDINFO data structure for the  }
{             specified drive.  RealModeAX = $6900 for a get and $6901 for a }
{             set operation.                                                 }
{----------------------------------------------------------------------------}

function GetSetMid (Drive: Byte; MID: PMIDINFO; RealModeAX: Word): Bool;
var
    Error: Byte;
begin
    { Assume everything ok }

    Error := 0;
    GetSetMid := True;

    R.ax := RealModeAX;
    R.bx := Drive;
    R.ds := HiWord (Longint (MID));              { Subtle !!! }
    R.dx := LoWord (Longint (MID));

    asm
        mov bx, 0021h     { set flags to $00, Real mode interrupt $21 }
        xor cx, cx        { copy 0 words from protected mode stack }
        mov ax, seg R
        mov es, ax        { selector of real mode call structure }
        mov di, offset R  { offset of real mode call structure }
        mov ax, 0300h     { DPMI simulate real mode interrupt }
        int 31h           { do the business }
        jnc @@1           { branch if no error }
        inc Error
    @@1:
    end;

    if Error = 1 then GetSetMid := False;
end;

{----------------------------------------------------------------------------}
{    Name:    GetMid                                                         }
{    Purpose: Get the MIDINFO record for a specified drive.                  }
{             Uses GetSetMid.  Returns TRUE if successful.                   }
{----------------------------------------------------------------------------}

function GetMid (drive: Byte; var mid: MIDINFO): Bool;
var
    p: LongInt;
begin
    { Assume failure }
    GetMid := False;

    { Allocate a MIDINFO data structure in DOS address-space }
    p := GlobalDOSAlloc (sizeof (MIDINFO));

    if GetSetMid (drive, Ptr (HiWord (p), 0), $6900) then
    begin
        mid := PMIDINFO (Ptr (LoWord (p), 0))^;
        GetMid := True;
    end;

    GlobalDOSFree (LoWord (p));
end;

{----------------------------------------------------------------------------}
{    Name:    SetMid                                                         }
{    Purpose: Set the MIDINFO record for a specified drive.                  }
{             Uses GetSetMid.  Returns TRUE if successful.                   }
{----------------------------------------------------------------------------}

function SetMid (drive: Byte; var mid: MIDINFO): Bool;
var
    p: LongInt;
begin
    { Assume failure }
    SetMid := False;

    { Allocate a MIDINFO data structure in DOS address-space }
    p := GlobalDOSAlloc (sizeof (MIDINFO));
    PMIDINFO (Ptr (LoWord (p), 0))^ := mid;
    if GetSetMid (drive, Ptr (HiWord (p), 0), $6901) then SetMid := True;
    GlobalDOSFree (LoWord (p));
end;

{----------------------------------------------------------------------------}
{    Name:    GetSerialNumber                                                }
{    Purpose: Get the serial number for a specified drive.                   }
{             If an error occurs, then 0 is returned as the serial number.   }
{----------------------------------------------------------------------------}

function GetSerialNumber (drive: Byte): LongInt;
var
    mid: MIDINFO;
begin
    if GetMid (drive, mid) then GetSerialNumber := mid.SerialNum
    else GetSerialNumber := 0;
end;

{----------------------------------------------------------------------------}
{    Name:    SetSerialNumber                                                }
{    Purpose: Set the serial number for a specified drive.                   }
{             If no error, TRUE is returned as the function result.          }
{----------------------------------------------------------------------------}

function SetSerialNumber (drive: Byte; serNum: LongInt): Bool;
var
    mid: MIDINFO;
begin
    SetSerialNumber := False;
    if GetMid (drive, mid) then
    begin
        mid.SerialNum := serNum;
        SetSerialNumber := SetMid (drive, mid);
    end;
end;

end.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mheacockCommented:
If you can set the serial number...what would prevent some
other program from doing the same thing, thus rendering
your program inoperable...thus pissing off your customer??

Reading drive serial numbers is just a bad idea.  Think about
it?  If it was a good idea, every major piece of software
would be doing it.

Also, what's to stop someone from just pirating your setup
disk??  Your setup doesn't know, ahead of time, the serial
number of the drive it is going to be installed to.
0
mheacockCommented:
What kind of software are you writing that you think it will
be so rampantly pirated?

If you are writing shareware or something, a better bet might
be to just supply demos that are time-stamped and will not
allows installs after an initial one has expired.

If you want some tips on how to do this effectively, I can
supply as an answer if you don't like the answer already given.
0
javiertbCommented:
And what if you change the system date? You could still be using the program.
0
mheacockCommented:
I've already taken into account changing the system date...
system date changes are a really simple problem to solve.

The simplest, though not the only solution, is to hard code
a date into your program that it cannot run before.  If
you created your program July 1996...you certainly would
not allow it to run with a system date of June 1996 or earlier.

There are a lot of other little things that you can do to
make it extremely difficult for anyone to try and circumvent
time-stamping.  It will always be possible to circumvent,
but if you make it a pain in the ass to do so, most folks will
stop bothering to try.

And you always have human error to rely on...the moment someone
forgets to set back the clock and run your program, it'll
make it very difficult for them to re-run it once it has
expired.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

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.