Solved

Getting HD Serial Number in win95/98

Posted on 2000-04-26
27
513 Views
Last Modified: 2012-06-21
How can I get the hard disk serial number under Windows 98. I am using C++. I have seen code that uses _inp and _outp . It works well under DOS but not Windows 98.

I have tried several _inp and _outp enabling dlls and liberaries to over the ring 3 limitation but they do not work always wrong values coming from the ports.

Your answer has to get the physical serial number of the HD. Not the volume serial number that you can get by GetVolumeInformation().

If you can also tell me how I can get a  checksum of the ROM biod it would be great but I will award the points even  if you just tell me the anwer for the first question.
0
Comment
Question by:sharifm
  • 13
  • 9
  • 2
  • +3
27 Comments
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2754052
Next article from MSDN:

The system VxD, VWIN32.VXD, supports the input and output control
(IOCTL) functions originally provided by MS-DOS Interrupt 21h.
The following example shows how to call Get Media ID
(Interrupt 21h Function 440Dh Minor Code 66h)
from a Win32-based application:

#define VWIN32_DIOC_DOS_IOCTL 1

typedef struct _DEVIOCTL_REGISTERS
{
    DWORD reg_EBX;
    DWORD reg_EDX;
    DWORD reg_ECX;
    DWORD reg_EAX;
    DWORD reg_EDI;
    DWORD reg_ESI;
    DWORD reg_Flags;
} DEVIOCTL_REGISTERS, *PDEVIOCTL_REGISTERS;

typedef struct _MID
{
    WORD  midInfoLevel;
    DWORD midSerialNum;
    BYTE  midVolLabel[11];
    BYTE  midFileSysType[8];
} MID, *PMID;

BOOL GetMediaID(PMID pmid, UINT nDrive)
{
    DEVIOCTL_REGISTERS reg;

    reg.reg_EAX = 0x440D;       // IOCTL for block devices
    reg.reg_EBX = nDrive;       // zero-based drive ID
    reg.reg_ECX = 0x0866;       // Get Media ID command
    reg.reg_EDX = (DWORD) pmid; // receives media ID info

    if (!DoIOCTL(&reg))
        return FALSE;

    if (reg.reg_Flags & 0x8000) // error if carry flag set
        return FALSE;

    return TRUE;
}

BOOL DoIOCTL(PDEVIOCTL_REGISTERS preg)
{
    HANDLE hDevice;

    BOOL fResult;
    DWORD cb;

    preg->reg_Flags = 0x8000; // assume error (carry flag set)

    hDevice = CreateFile("\\\\.\\vwin32",
        GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
        (LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);

    if (hDevice == (HANDLE) INVALID_HANDLE_VALUE)
        return FALSE;
    else
    {
        fResult = DeviceIoControl(hDevice, VWIN32_DIOC_DOS_IOCTL,
            preg, sizeof(*preg), preg, sizeof(*preg), &cb, 0);

        if (!fResult)
            return FALSE;
    }

    CloseHandle(hDevice);

    return TRUE;
}
0
 
LVL 22

Expert Comment

by:nietod
ID: 2754677
You might want to look at

http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=3&txtCodeId=174

part of the code it generates comes from the HD serial number.
0
 

Author Comment

by:sharifm
ID: 2757669
to nietod,

The code there calls GetVolumeInformation which gets the DOS serial number in the boot sector. This can be easily changed and so your software  would be easily hacked.

I still need to try the code Alex sent, but I am suspecting it returns the same thing as GetVolumeInformation. I will try it in a matter of hours.
0
 
LVL 22

Expert Comment

by:nietod
ID: 2757733
I am aware of GetVolumenIformation()'s weakness (as a security measure, not really a weakness in its function...)    But the documentation seemed to suggest that it was getting the serial number.   Maybe I read it wrong.

If Alex's code works, it should not be returinging the windows volume serial number.  This is much lower leve than that.  My concern woudl be do all HD devices respond to this device I/O control.   Under DOS it was not safe to assume so, as not all devices even had serial numbers.  Maybe these days they all do.  Alex woudl probably know more than I though.
0
 

Author Comment

by:sharifm
ID: 2757922
I tried Alex's code. It came out with a number different from both the actual HD serial and also the volume serial number. I do not think it is the correct one too. The other call can also return controller revision number and HD model number.

I am posting below the ideal code I want to function. It works well under dos. I found it elsewhere on Expert-Exchange. it is great but does not work on win98. The ports never gie the right values. look at it and tell me if you can suggest anything. here it is:

/*
** DUG_IDE : Provides IDE disk info on both drives in the system
**           Version 1.0
**
** Copyright (c) 12 Jan 1993 by Doug Merrett - All rights reserved
**
** Postal Address: PO Box 432
**                 Stones Corner  Q  4120
**                 Australia
**
** Email Address:  dcm@mincom.oz.au
**
** You may distribute freely, but no modifications without mailing me a copy.
** No profit can be made for distribution.  Blah Blah Blah etc.
*/

/* Used by JPI for clrscr */
#define _JPI_WIN_


#include <stdlib.h>
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <bios.h>


char *getascii (unsigned int in_data [], int off_start, int off_end);

void main (void)
{
  unsigned int dd [256]; /* DiskData */
  unsigned int dd_off;   /* DiskData offset */
  unsigned int loop;     /* Loop variable */
  int num_drv;           /* Number of Hard disks */

  union REGS registers;  /* Used for Interrupt for BIOS data */


  unsigned int bios_cyl [2], bios_head [2], bios_sec [2];  /* Cylinders, Heads, Sectors */


  clrscr ();

  fprintf (stderr, "** DUG_IDE : Provides IDE disk info on both drives in the system\n");
  fprintf (stderr, "** Version 1.0\n");
  fprintf (stderr, "**\n");
  fprintf (stderr, "** Copyright (c) 12 Jan 1993 by Doug Merrett - All rights reserved\n");
  fprintf (stderr, "**\n");
  fprintf (stderr, "** Postal Address: PO Box 432\n");
  fprintf (stderr, "**                 Stones Corner  Q  4120\n");
  fprintf (stderr, "**                 Australia\n");
  fprintf (stderr, "**\n");
  fprintf (stderr, "** Email Address:  dcm@mincom.oz.au\n");
  fprintf (stderr, "**\n");
  fprintf (stderr, "** You may distribute freely, but no modifications without mailing me a copy.\n");
  fprintf (stderr, "** No profit can be made for distribution.  Blah Blah Blah etc.\n\n");
  fprintf (stderr, "Press any key to accept above limitations");
  getch ();

  /* How many disk drives & parameters */
  num_drv = peekb (0x40, 0x75);  /* BIOS Data area, Number of Hard disks */
                                 /* Byte at Segment 40H Offset 75H */

  for (loop = 0; loop < num_drv; loop++)  /* Loop through drives */
    {
      /* Get IDE Drive info */

      while (inp (0x1F7) != 0x50)  /* Wait for controller not busy */
        ;

      outp (0x1F6, (loop == 0 ? 0xA0 : 0xB0)); /* Get first/second drive */

      outp (0x1F7, 0xEC);          /* Get drive info data */

      while (inp (0x1F7) != 0x58)  /* Wait for data ready */
        ;

      for (dd_off = 0; dd_off != 256; dd_off++) /* Read "sector" */
        dd [dd_off] = inpw (0x1F0);

      /* Get BIOS drive info */
      registers.h.ah = 0x8;            /* Get drive info */
      registers.h.dl = 0x80 + loop;    /* Drive is 80H for Disk 0, 81H for Disk 1 */
      int86 (0x13, &registers, &registers);
      if (! registers.x.cflag)   /* All OK if carry not set */
        {
          bios_head [loop] = registers.h.dh + 1; /* Heads are from 0 */
          bios_sec [loop] = registers.h.cl & 0x3F; /* sec is bits 5 - 0 */
          bios_cyl [loop] = ((registers.h.cl & 0xC0) << 2) + registers.h.ch + 2; /* +1 because starts from 0 and +1 for FDISK leaving one out */
        }

      clrscr ();

      fprintf (stdout, "DRIVE %d:\n", loop);
      fprintf (stdout, "Model Number______________________: %s\n", getascii (dd, 27, 46));
      fprintf (stdout, "Serial Number_____________________: %s\n", getascii (dd, 10, 19));
      fprintf (stdout, "Controller Revision Number________: %s\n\n", getascii (dd, 23, 26));
      fprintf (stdout, "Able to do Double Word Transfer___: %6s\n", (dd [48] == 0 ? "No" : "Yes"));
      fprintf (stdout, "Controller type___________________:   %04X\n", dd [20]);
      fprintf (stdout, "Controller buffer size (bytes)____: %6u\n", dd [21] * 512);
      fprintf (stdout, "Number of ECC bytes transferred___: %6u\n", dd [22]);
      fprintf (stdout, "Number of sectors per interrupt___: %6u\n\n", dd [47]);
      fprintf (stdout, "Hard Disk Reports\n");
      fprintf (stdout, "Number of Cylinders (Fixed)_______: %6u\n", dd [1]);
      fprintf (stdout, "Number of Heads___________________: %6u\n", dd [3]);
      fprintf (stdout, "Number of Sectors per Track_______: %6u\n\n", dd [6]);
      fprintf (stdout, "BIOS Reports\n");
      fprintf (stdout, "Number of Cylinders_______________: %6u\n", bios_cyl [loop]);
      fprintf (stdout, "Number of Heads___________________: %6u\n", bios_head [loop]);
      fprintf (stdout, "Number of Sectors per Track_______: %6u\n\n", bios_sec [loop]);

      if (! loop)
        {
          fprintf (stdout, "Press a key");
          getch ();
        }
   }
}

char *getascii (unsigned int in_data [], int off_start, int off_end)
{
  static char ret_val [255];
  int loop, loop1;

  for (loop = off_start, loop1 = 0; loop <= off_end; loop++)
    {
      ret_val [loop1++] = (char) (in_data [loop] / 256);  /* Get High byte */
      ret_val [loop1++] = (char) (in_data [loop] % 256);  /* Get Low byte */
    }
  ret_val [loop1] = '\0';  /* Make sure it ends in a NULL character */
  return (ret_val);
}
0
 

Author Comment

by:sharifm
ID: 2761038
Adjusted points from 100 to 200
0
 

Author Comment

by:sharifm
ID: 2775111
Adjusted points from 200 to 300
0
 

Author Comment

by:sharifm
ID: 2815622
Adjusted points from 300 to 400
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2815841
I have an idea :
You can make DOS utility from  you code,
that saves result(Serial Number of HD) in file, include this utility in you paket, run it in begin of you apps (for example), and read result from disk. Very simple!
0
 

Author Comment

by:sharifm
ID: 2816356
I thought of that, but did not work for me for 2 reasons:
1) it does not work all the time from a dos box (unreliable)

2) a very weak link in a copy protection progrm that hackers can use to decrypt the file or debug the dos code.
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2818242
>>1) it does not work all the time from a dos box (unreliable)

I don't understand, what does not work?
May be programm open Dos window? Use
ShellExecute with SW_HIDE parameter
and you DOS apps will be invisible

>>2) a very weak link in a copy protection progrm that hackers can use to decrypt the file or debug the dos code.
 
You can link you exe module to you
main apps as user-defined resource,
load it in memory by LoadResource,
save to disk, launch and after end of
exe module delete this one, and i doubte, that any haker can see it!

0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2829094
I think, you can convert you code to Win32. Maun thing: inp/outp function.
Simple must write them!
next is discussion (for BCB, but it is ~ same):
Discussion of Port I/O under NT:
http://users.skynet.be/k-net/ParPort/index.html
http://www.bcbdev.com/faqs/faq30.htm

> Harold Howe has contributed something that you might be able to use
> under win95 only:
> http://www.bcbdev.com/components.htm

Or EnTech's Port I/O component:
http://www.entechtaiwan.com/tools.htm

Or, for Win9x only, if you have TASM, you can use the following:

#define outportb(port,val) outb(val,port)

void __fastcall outb(Byte val, WORD port)
{
asm out dx,al
}

#define inportb(port) inb(0,port)

Byte __fastcall inb(Byte dummy, WORD port)
{
asm in al,dx
}  
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2973330
sharifm, next is an example using
inp/outp function in Windows95
Example reads Serial Number of HD
For making inp/outp I use Winio.dll
from www.sysinternals.com(that works in all Windows versions)
You can download Winio.dll
from sysinternals or i can send you
with full text:

/*
** DUG_IDE : Provides IDE disk info on all (up to 8) drives in the system
**           Version 2.0
**
** Copyright (c) 26 Apr 1998 by Doug Merrett - All rights reserved
**
** Email Address:  dcm@ozemail.com.au
**
** You may distribute freely, but no modifications without mailing me a copy.
** No profit can be made for distribution.  Blah Blah Blah etc.
*/

#include <windows.h>
#include <stdlib.h>
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include "port32.h"

int inp(unsigned portId);
int outp(unsigned portId, int value);
int inpw(unsigned portId);

char *getascii (unsigned short in_data [], unsigned short off_start, unsigned short off_end);
int main (void)
{
  unsigned short dd [256];   /* DiskData */
  unsigned short dd_off;     /* DiskData offset */
  unsigned short drive;      /* Loop variable */
  unsigned long  wait_loop;  /* Timeout loop */
  unsigned short base;       /* Base address of drive controller */
  unsigned short in_val;


  clrscr ();
  fprintf (stderr, "** DUG_IDE : Provides IDE disk info on both drives in the system\n");
  fprintf (stderr, "** Version 2.0\n");
  fprintf (stderr, "**\n");
  fprintf (stderr, "** Copyright (c) 12 Jan 1993 by Doug Merrett - All rights reserved\n");
  fprintf (stderr, "**               25 Apr 1998 by Doug Merrett - Version 2.0\n");
  fprintf (stderr, "**\n");
  fprintf (stderr, "** Email Address:  dcm@ozemail.com.au\n");
  fprintf (stderr, "**\n");
  fprintf (stderr, "** You may distribute freely, but no modifications without mailing me a copy.\n");
  fprintf (stderr, "** No profit can be made for distribution.  Blah Blah Blah etc.\n");
  fprintf (stderr, "**\n");
  fprintf (stderr, "** The newer features in this release owe a great deal to Ralf Brown's\n");
  fprintf (stderr, "** Interrrupt List as I used the PORTS.LST file to get some more detailed\n");
  fprintf (stderr, "** information about the results passed back by the drive.\n\n");

  fprintf (stderr, "Press any key to accept above limitations");

  getch ();

  for (drive = 0; drive < 8; drive++)  /* Loop through drives */
    {
      /* Get IDE Drive info */

      switch (drive / 2)
        {
        case 0: base = 0x1f0;
                break;
        case 1: base = 0x170;
                break;
        case 2: base = 0x1e8;
                break;
        case 3: base = 0x168;
                break;
        }

      /* Wait for controller not busy */
      wait_loop = 100000;
      while (--wait_loop > 0)
        {
           in_val = inp (base + 7);
           if (((in_val & 0x40) == 0x40) || ((in_val & 0x00) == 0x00))
             break;
        }

      if (wait_loop < 1)
        continue;

      outp (base + 6, ((drive % 2) == 0 ? 0xA0 : 0xB0)); /* Get Master/Slave drive */

      outp (base + 7, 0xEC);          /* Get drive info data */

      /* Wait for data ready */
      wait_loop = 100000;
      while (--wait_loop > 0)
        {
        in_val = inp (base + 7);
        if ((in_val & 0x48) == 0x48) /* drive ready and needs service */
          break;
        if ((in_val & 0x01) == 0x01) /* drive error */
          break;
        }

      if ((wait_loop < 1) || ((in_val & 0x01) == 0x01)) /* Timed Out or Error */
        continue;

      for (dd_off = 0; dd_off != 256; dd_off++) /* Read "sector" */
        dd [dd_off] = inpw (base);

      clrscr ();
      switch (drive / 2)
        {
        case 0: fprintf (stdout, "Primary ");
                break;
        case 1: fprintf (stdout, "Secondary ");
                break;
        case 2: fprintf (stdout, "Tertiary ");
                break;
        case 3: fprintf (stdout, "Quaternary ");
                break;
        }

      fprintf (stdout, "Controller - ");

      switch (drive % 2)
        {
        case 0: fprintf (stdout, "Master");
                break;
        case 1: fprintf (stdout, "Slave");
                break;
        }

      fprintf (stdout, " drive\n\n");

      fprintf (stdout, "Model Number______________________: %s\n", getascii (dd, 27, 46));
      fprintf (stdout, "Serial Number_____________________: %s\n", getascii (dd, 10, 19));
      fprintf (stdout, "Controller Revision Number________: %s\n\n", getascii (dd, 23, 26));
      if (dd [80] != 0 && dd [80] != 0xFFFF)
        fprintf (stdout, "ATA Version Number________________: %u.%u\n", dd [80], (dd [81] == 0xFFFF ? 0 : dd [81]));

      fprintf (stdout, "Able to do Double Word Transfer___: %s\n", (dd [48] == 0 ? "No" : "Yes"));
      fprintf (stdout, "Controller buffer size (bytes)____: %u\n", dd [21] * 512);
      fprintf (stdout, "Transfer Speed____________________: ");
      if (dd [0] & 0x0400)
        fprintf (stdout, "> 10 Mbit/sec\n");
      if (dd [0] & 0x0200)
        fprintf (stdout, "5-10 Mbit/sec\n");
      if (dd [0] & 0x0100)
        fprintf (stdout, "< 5 Mbit/sec\n");
      fprintf (stdout, "Drive Type________________________: ");
      if (dd [0] & 0x0080)
        fprintf (stdout, "Removable\n");
      if (dd [0] & 0x0040)
        fprintf (stdout, "Fixed\n");
      fprintf (stdout, "IORDY Supported___________________: %s\n", ((dd [49] & 0x0800) ? "Yes" : "No"));
      fprintf (stdout, "Can IORDY be disabled by device___: %s\n", ((dd [49] & 0x0400) ? "Yes" : "No"));
      fprintf (stdout, "LBA Mode supported________________: %s\n", ((dd [49] & 0x0200) ? "Yes" : "No"));
      fprintf (stdout, "DMA Supported_____________________: %s\n", ((dd [49] & 0x0100) ? "Yes" : "No"));
      fprintf (stdout, "Number of ECC bytes transferred___: %u\n", dd [22]);
      fprintf (stdout, "Number of sectors per interrupt___: %u\n\n", dd [47] % 256);
      fprintf (stdout, "Number of Cylinders_______________: %u\n", dd [1]);
      fprintf (stdout, "Number of Heads___________________: %u\n", dd [3]);
      fprintf (stdout, "Number of Sectors per Track_______: %u\n\n", dd [6]);

      fprintf (stdout, "Press a key");
      fflush (stdout);
      getch ();

    }
  return 1;
}

char *getascii (unsigned short in_data [], unsigned short off_start, unsigned short off_end)
{
  static char ret_val [255];
  int loop, loop1;

  for (loop = off_start, loop1 = 0; loop <= off_end; loop++)
    {
      ret_val [loop1++] = (char) (in_data [loop] / 256);  /* Get High byte */
      ret_val [loop1++] = (char) (in_data [loop] % 256);  /* Get Low byte */
    }
  ret_val [loop1] = '\0';  /* Make sure it ends in a NULL character */
  return (ret_val);
}
//now most interesting for you part
//using functions from Winio.dll
int inp(unsigned portId)
{
  DWORD wPortVal;
  GetPortVal(portId, &wPortVal, 1);
  return wPortVal;
}
int inpw(unsigned portId)
{
  DWORD wPortVal;
  GetPortVal(portId, &wPortVal, 2);
  return wPortVal;
}
int outp(unsigned portId, int value)
{
  SetPortVal(portId, value, 1);
  return value;
}
H file port32.h
#ifndef PORT32_H
#define PORT32_H

//#ifdef WINIO_DLL
#define PORT32API _declspec(dllexport)

extern "C"
{
  bool _stdcall GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize);
  bool _stdcall SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize);
}

#endif

Alex



0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 

Author Comment

by:sharifm
ID: 2974515
Thank you Aex,
But my problem. is that I cannot use a dll. I am making a copy protection software. calling a dll for IO will make it very easy to break my protection. I am looking for a solution that either is in source code format or as a LIB that I can embed inside my own DLL. without an external dll call.

In case you are wondering about my dll. I encrypt the calls from my apps to my dll. I will not be able to do that with third party software.

Thank's again Alex, you are doing great. Please keep it up.
0
 

Author Comment

by:sharifm
ID: 2974551
Adjusted points from 400 to 500
0
 
LVL 14

Accepted Solution

by:
AlexVirochovsky earned 500 total points
ID: 2976912
O, if you don't want use DLL, you can use source text of winio (not all, only
port32.cpp)
Full text you can get from sysinternals
(or I can send you). Next is snippet:

#include <windows.h>
#include <winioctl.h>
#include "port32.h"
#include "drv\winio.h"
#include "general.h"

// These are our ring 0 functions responsible for tinkering with the hardware ports.
// They have a similar privilege to a Windows VxD and are therefore free to access
// protected system resources (such as the page tables) and even place calls to
// exported VxD services.

__declspec(naked) void Ring0GetPortVal()
{
  _asm
  {
    Cmp CL, 1
    Je ByteVal
    Cmp CL, 2
    Je WordVal
    Cmp CL, 4
    Je DWordVal

ByteVal:

    In AL, DX
    Mov [EBX], AL
    Retf

WordVal:

    In AX, DX
    Mov [EBX], AX
    Retf

DWordVal:

    In EAX, DX
    Mov [EBX], EAX
    Retf
  }
}

__declspec(naked) void Ring0SetPortVal()
{
  _asm
  {
    Cmp CL, 1
    Je ByteVal
    Cmp CL, 2
    Je WordVal
    Cmp CL, 4
    Je DWordVal

ByteVal:

    Mov AL, [EBX]
    Out DX, AL
    Retf

WordVal:

    Mov AX, [EBX]
    Out DX, AX
    Retf

DWordVal:

    Mov EAX, [EBX]
    Out DX, EAX
    Retf
  }
}

// This function makes it possible to call ring 0 code from a ring 3
// application.

bool CallRing0(PVOID pvRing0FuncAddr, WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize)
{

  GDT_DESCRIPTOR *pGDTDescriptor;
  GDTR gdtr;

  _asm Sgdt [gdtr]

  // Skip the null descriptor

  pGDTDescriptor = (GDT_DESCRIPTOR *)(gdtr.dwGDTBase + 8);

  // Search for a free GDT descriptor

  for (WORD wGDTIndex = 1; wGDTIndex < (gdtr.wGDTLimit / 8); wGDTIndex++)
  {
    if (pGDTDescriptor->Type == 0     &&
        pGDTDescriptor->System == 0   &&
        pGDTDescriptor->DPL == 0      &&
        pGDTDescriptor->Present == 0)
    {
      // Found one !
      // Now we need to transform this descriptor into a callgate.
      // Note that we're using selector 0x28 since it corresponds
      // to a ring 0 segment which spans the entire linear address
      // space of the processor (0-4GB).

      CALLGATE_DESCRIPTOR *pCallgate;

      pCallgate =      (CALLGATE_DESCRIPTOR *) pGDTDescriptor;
      pCallgate->Offset_0_15 = LOWORD(pvRing0FuncAddr);
      pCallgate->Selector = 0x28;
      pCallgate->ParamCount =      0;
      pCallgate->Unused = 0;
      pCallgate->Type = 0xc;
      pCallgate->System = 0;
      pCallgate->DPL = 3;
      pCallgate->Present = 1;
      pCallgate->Offset_16_31 = HIWORD(pvRing0FuncAddr);

      // Prepare the far call parameters

      WORD CallgateAddr[3];

      CallgateAddr[0] = 0x0;
      CallgateAddr[1] = 0x0;
      CallgateAddr[2] = (wGDTIndex << 3) | 3;

      // Please fasten your seat belts!
      // We're about to make a hyperspace jump into RING 0.

      _asm Mov DX, [wPortAddr]
      _asm Mov EBX, [pdwPortVal]
      _asm Mov CL, [bSize]
      _asm Call FWORD PTR [CallgateAddr]

      // We have made it !
      // Now free the GDT descriptor

      memset(pGDTDescriptor, 0, 8);

      // Our journey was successful. Seeya.

      return true;
    }

    // Advance to the next GDT descriptor

    pGDTDescriptor++;
  }

  // Whoops, the GDT is full

  return false;
}


bool _stdcall GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize)
{
  bool Result;
  DWORD dwBytesReturned;
  tagPort32Struct Port32Struct;

  if (IsNT)
  {
    if (!IsWinIoInitialized)
      return false;

    Port32Struct.wPortAddr = wPortAddr;
    Port32Struct.bSize = bSize;

    if (!DeviceIoControl(hDriver, IOCTL_WINIO_READPORT, &Port32Struct,
                         sizeof(tagPort32Struct), &Port32Struct, sizeof(tagPort32Struct),
                         &dwBytesReturned, NULL))
      return false;
    else
      *pdwPortVal = Port32Struct.dwPortVal;
  }
  else
  {
    Result = CallRing0((PVOID)Ring0GetPortVal, wPortAddr, pdwPortVal, bSize);

    if (Result == false)
      return false;
  }

  return true;
}


bool _stdcall SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize)
{
  DWORD dwBytesReturned;
  tagPort32Struct Port32Struct;

  if (IsNT)
  {
    if (!IsWinIoInitialized)
      return false;

    Port32Struct.wPortAddr = wPortAddr;
    Port32Struct.dwPortVal = dwPortVal;
    Port32Struct.bSize = bSize;

    if (!DeviceIoControl(hDriver, IOCTL_WINIO_WRITEPORT, &Port32Struct,
                         sizeof(tagPort32Struct), NULL, 0, &dwBytesReturned, NULL))
      return false;
  }
  else
    return CallRing0((PVOID)Ring0SetPortVal, wPortAddr, &dwPortVal, bSize);
 
  return true;
}
0
 

Author Comment

by:sharifm
ID: 2977874
>>Alex,
I think we are on the right track here. I searched sysinternals for winio, but could not find it. Please give me its exact location or send me the files. This time it looks great. Thanx
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2979663
Write you EMail, i 'll send you
(and my example too).
Alex
0
 

Author Comment

by:sharifm
ID: 2982304
>>Alex
sharif@motawally.com

thank you so much
Sharif
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2984734
done.
0
 

Author Comment

by:sharifm
ID: 3000776
Comment accepted as answer
0
 

Author Comment

by:sharifm
ID: 3000777
Great code. Can be used in many other situations too.

Alex is great
0
 
LVL 1

Expert Comment

by:Nevering
ID: 3940132
Alex... could I also get a copy of the code that you sent to Sharifm? My email is ken@ishere.com

thanks
Nev
0
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 3967870
Done
0
 
LVL 6

Expert Comment

by:snoegler
ID: 7006382
Extremely interesting solution :)

Does anyone know if this will still work in Windows XP or future versions? Is this considered a security problem at MS?
0
 

Author Comment

by:sharifm
ID: 7007629
It will work, but you have to use another version of WinIo for Windows NT with a VXD. That version will run on Win NT, 2000, XP.

Not a security problem but generally the OS should be the one directly accessing the Hardware. Hence why Windows makes it difficult to do this. This assures stability to the OS from badly behaving apps.
0
 

Expert Comment

by:shaharAmitai
ID: 25887653
could I also get a copy of the code that you sent to Sharifm? My email is shahar@icomobile.com

thanks
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

747 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now