Page 2 of 3

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Mon Jun 09, 2014 5:35 pm
by Antonio Linares
Esta versión corrige un error de la anterior pero aún no está dando la información que buscamos:

Code: Select all  Expand view
#pragma BEGINDUMP

#include <hbapi.h>
#include <Windows.h>

HB_FUNC( TEST )
{
   HANDLE disk0;
   DWORD retCount, dwRet = 0;
   // GETVERSIONINPARAMS versionInfo;
   SENDCMDINPARAMS stCIP;
   char szOutput[ 512 + 16 ]; // OUT_BUFFER_SIZE IDENTIFY_BUFFER_SIZE+16

   /* get a handle for physical disk 0 (the C: drive) */
   if ((disk0 = CreateFile (
      L"\\\\.\\PhysicalDrive0",
      GENERIC_READ,
      NULL,
      NULL,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL,
      NULL)) == INVALID_HANDLE_VALUE)
   {
      MessageBox( 0, "1", "Info", 0 );
      return;
   }

    memset( szOutput, 0, sizeof( szOutput ) );

    #define DRIVE_HEAD_REG  0xA0

    stCIP.cBufferSize=IDENTIFY_BUFFER_SIZE;
    stCIP.bDriveNumber = 0; // ucDriveIndex;
    stCIP.irDriveRegs.bFeaturesReg= 0;
    stCIP.irDriveRegs.bSectorCountReg = 1;
    stCIP.irDriveRegs.bSectorNumberReg = 1;
    stCIP.irDriveRegs.bCylLowReg = 0;
    stCIP.irDriveRegs.bCylHighReg = 0;
    stCIP.irDriveRegs.bDriveHeadReg = DRIVE_HEAD_REG;
    stCIP.irDriveRegs.bCommandReg = ID_CMD;

    if ( DeviceIoControl( disk0, SMART_RCV_DRIVE_DATA, &stCIP, sizeof(stCIP), szOutput, 512 + 16,
         &dwRet, NULL) )
    {
       MessageBox( 0, "pasa", "ok", 0 );
    }

   MessageBox( 0, szOutput, "buffer", 0 );

/* close everything & go home */
   CloseHandle (disk0);
   // hb_retclen( szOutput, dwRet );
}

#pragma ENDDUMP

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Mon Jun 09, 2014 5:39 pm
by Antonio Linares
Esta es la mejor versión que he encontrado hasta ahora para el uso del interface SMART.

Ahora se trata de buscar aqui los valores que necesitas:

http://munin-monitoring.org/browser/munin-node-win32/src/plugins/disk/SmartReader.cpp

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Mon Jun 09, 2014 6:28 pm
by Antonio Linares
Prueba con esta:

Code: Select all  Expand view
#pragma BEGINDUMP

#include <hbapi.h>
#include <Windows.h>

HB_FUNC( TEST )
{
     char szVolumeLetter[32];
     char szPhysicalDrive[64];

     HANDLE hPhysicalDriveIOCTL = CreateFile(L"\\\\.\\PhysicalDrive0", GENERIC_READ | GENERIC_WRITE,

                FILE_SHARE_READ  | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

     if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)

     {

                DWORD dwBytesReturned = 0;

         

                // Get Physical Drive Information

                VOLUME_DISK_EXTENTS   vdExtents;
                GETVERSIONINPARAMS  gvopVersionParams;


                ZeroMemory(&vdExtents,   sizeof(vdExtents));

                if(!DeviceIoControl(hPhysicalDriveIOCTL,   IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,  NULL, 0,

                     &vdExtents,   sizeof(vdExtents),  &dwBytesReturned, NULL)){

                     MessageBox( 0 , "Error   volumes  that span multiple disks are not supported!", "sorry", 0 );

                     CloseHandle(hPhysicalDriveIOCTL);

                     return    1;

                }



                // Get SMART version information

                ZeroMemory(&gvopVersionParams,   sizeof(gvopVersionParams));

                if(!DeviceIoControl(hPhysicalDriveIOCTL,   SMART_GET_VERSION,  NULL, 0,

                     &gvopVersionParams ,  sizeof(gvopVersionParams), &dwBytesReturned, NULL)){

                     MessageBox( 0, "Error   cannot  get SMART version information from device!", "warning", 0 );

                     CloseHandle(hPhysicalDriveIOCTL);

                return 1;

                }

       

                if(gvopVersionParams.bIDEDeviceMap > 0)

                {

                     // Setup SMART request

                     SENDCMDINPARAMS   InParams  = {

                             IDENTIFY_BUFFER_SIZE,  { 0, 1, 1, 0, 0, ((vdExtents.Extents[0].DiskNumber & 1) ? 0xB0 : 0xA0),

                             ((gvopVersionParams.bIDEDeviceMap  >> vdExtents.Extents[0].DiskNumber & 0x10) ? ATAPI_ID_CMD : ID_CMD) },

                             (BYTE)vdExtents.Extents [0].DiskNumber

                     };
 
                       

                       DWORD dwBufSize = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;

                     SENDCMDOUTPARAMS pbtIDOutCmd; //   = (PSENDCMDOUTPARAMS) new BYTE[dwBufSize];

                     ZeroMemory(&pbtIDOutCmd,  dwBufSize);

                     
 
                       // Get SMART information

                     if(DeviceIoControl (hPhysicalDriveIOCTL, SMART_RCV_DRIVE_DATA, &InParams, sizeof(SENDCMDINPARAMS),

                             &pbtIDOutCmd,  dwBufSize, &dwBytesReturned, NULL))

                     {

                           // Little Endian To Big Endian

                             USHORT  *pIDSector = (USHORT*)pbtIDOutCmd.bBuffer;
                             int nShort;
                             char lpszSerialNumber1[ 21 ];
                             LPSTR  lpszSerialNumber2;

                             for( nShort = 10; nShort < 21; nShort++)

                                   pIDSector [nShort] = (((pIDSector[nShort] & 0x00FF) << 8) + ((pIDSector[nShort] & 0xFF00) >> 8));

                           

                            // Get Drive Serial Number

                             ZeroMemory(lpszSerialNumber1, 21);

                             RtlCopyMemory(lpszSerialNumber1,  &pIDSector[10], 20);

                           

                            // Remove those horrible spaces caused because of endianess

                           // and print out the serial

                             lpszSerialNumber2 = lpszSerialNumber1;

                             while(*lpszSerialNumber2  == ' ') lpszSerialNumber2++;

                             MessageBox( 0, "Physical  Serial:", lpszSerialNumber2, 0);

                             // delete  lpszSerialNumber1;

                     }

                     // delete    pbtIDOutCmd;
 
               

                }else{
 
                     printf ("Error  !\n");

                     CloseHandle(hPhysicalDriveIOCTL);

                     return    1;

                }

                CloseHandle  (hPhysicalDriveIOCTL);
   }
}

#pragma ENDDUMP

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 12:23 am
by cuatecatl82
Probando y compilando,

Resultados:

El primer código que me sugirio al llmarlo comoTEST() no hace nada, no aparece nada, si lo invoco como MSGINFO(TEST()) aparece "nil"

El segundo código solo muestra un msgbox con "Info 1"

El tercer código no compila salen errores y warnings:

Warning W8075 hardDsk.c 13: Suspicious pointer conversion in function HB_FUN_TEST
Warning W8081 hardDsk.c 39: void functions may not return a value in function HB_FUN_TEST
Warning W8081 hardDsk.c 57: void functions may not return a value in function HB_FUN_TEST
Error E2063 hardDsk.c 71: Illegal initialization in function HB_FUN_TEST
Warning W8081 hardDsk.c 142: void functions may not return a value in function HB_FUN_TEST
Warning W8067 hardDsk.c 148: Both return and return with a value used in function HB_FUN_TEST


Aqui le dejo los fuentes del programa CrystalDiskInfo, que es en lo que me estoy basando.. Mis conocimientos en C son escasos para el nivel de programación de estos codigos..

https://www.mediafire.com/?vcwmzmfypgbv7lf

Saludos..

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 7:59 am
by Antonio Linares
Este código fuenciona correctamente compilando con Visual Studio, pero falla con Borland (aún no he encontrado por que no funciona con Borland):

serial.prg
Code: Select all  Expand view
#include "FiveWin.ch"

//----------------------------------------------------------------------------//

function Main()

   MsgInfo( SerialNumber() )

return nil

//----------------------------------------------------------------------------//

#pragma BEGINDUMP

#include <hbapi.h>
#include <Windows.h>

HB_FUNC(SERIALNUMBER)
{
    HANDLE hPhysicalDriveIOCTL = 0;

    hPhysicalDriveIOCTL = (HANDLE)CreateFile(L"\\\\.\\PhysicalDrive0", 0,
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
        OPEN_EXISTING, 0, NULL);

    if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    {
        STORAGE_PROPERTY_QUERY query;
        DWORD cbBytesReturned = 0;
        char buffer[10000];

        memset((void *)&query, 0, sizeof(query));
        query.PropertyId = StorageDeviceProperty;
        query.QueryType = PropertyStandardQuery;

        memset(buffer, 0, sizeof(buffer));

        if (DeviceIoControl(hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY,
            &query,
            sizeof(query),
            &buffer,
            sizeof(buffer),
            &cbBytesReturned, NULL))
        {
            hb_retclen(buffer + 126, 20);
        }
    }
}

#pragma ENDDUMP


Image

Image

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 8:13 am
by Antonio Linares
Funcionando con Borland :-)

serial.prg
Code: Select all  Expand view
#include "FiveWin.ch"

//----------------------------------------------------------------------------//

function Main()

   MsgInfo( SerialNumber() )
   
return nil

//----------------------------------------------------------------------------//

#pragma BEGINDUMP

#include <hbapi.h>
#include <Windows.h>

#define IOCTL_STORAGE_QUERY_PROPERTY 0x2D1400

typedef struct _STORAGE_PROPERTY_QUERY {
  int PropertyId;
  int QueryType;
  BYTE AdditionalParameters[ 1 ];
} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;

HB_FUNC( SERIALNUMBER )
{
    HANDLE hPhysicalDriveIOCTL = ( HANDLE ) CreateFile( "\\\\.\\PhysicalDrive0", 0,
                                   FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                                   OPEN_EXISTING, 0, NULL);

    if( hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE )
    {
        STORAGE_PROPERTY_QUERY query;
        DWORD cbBytesReturned = 0;
        char buffer[ 10000 ];

        memset( ( void * ) &query, 0, sizeof( query ) );
        query.PropertyId = 0; // StorageDeviceProperty;
        query.QueryType = 0;  // PropertyStandardQuery;

        memset( buffer, 0, sizeof( buffer ) );

        if( DeviceIoControl( hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY,
              &query,
              sizeof( query ),
              &buffer,
              sizeof( buffer ),
              &cbBytesReturned, NULL ) )
        {
           hb_retclen( buffer + 126, 20 );
        }
        else
           hb_retc( "can't read it" );
    }
    else
           hb_retc( "can't read it" );
}

#pragma ENDDUMP


Image

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 12:49 pm
by cuatecatl82
Maestro Buen día, me levante de madrugada emocionado por probar, pero en mi caso no funciona, talvez el sistema operativo me limita pues lo estoy probando bajo Xp, instale W7 en una máquina virtual y ahí si funciona, no entiendo porque no funciona, es bastante estresante no poder avanzar..

Ooh Oohh y al parecer mi disco duro voló, al reiniciar mi equipo ya no lo hizo, ojala y no pierda todo otra vez.. Veré que puedo hacer.. Me indica error partition table

Saludos

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 1:05 pm
by Antonio Linares
Victor,

Pruébalo así:

serial.prg
Code: Select all  Expand view
#include "FiveWin.ch"

//----------------------------------------------------------------------------//

function Main()

   MsgInfo( SerialNumber() )
   
return nil

//----------------------------------------------------------------------------//

#pragma BEGINDUMP

#include <hbapi.h>
#include <Windows.h>

#define IOCTL_STORAGE_QUERY_PROPERTY 0x2D1400

typedef struct _STORAGE_PROPERTY_QUERY {
  int PropertyId;
  int QueryType;
  BYTE AdditionalParameters[ 1 ];
} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;

HB_FUNC( SERIALNUMBER )
{
    HANDLE hPhysicalDriveIOCTL = ( HANDLE ) CreateFile( "\\\\.\\PhysicalDrive0", 0,
                                                                                     FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

    if( hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE )
    {
        STORAGE_PROPERTY_QUERY query;
        DWORD cbBytesReturned = 0;
        char buffer[ 10000 ];

        memset( ( void * ) &query, 0, sizeof( query ) );
        query.PropertyId = 0; // StorageDeviceProperty;
        query.QueryType = 0;  // PropertyStandardQuery;

        memset( buffer, 0, sizeof( buffer ) );

        if( DeviceIoControl( hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY,
              &query,
              sizeof( query ),
              &buffer,
              sizeof( buffer ),
              &cbBytesReturned, NULL ) )
        {
           hb_retclen( buffer + 126, 20 );
        }
        else
           hb_retc( "can't read it" );
           
        CloseHandle( hPhysicalDriveIOCTL );  
    }
    else
           hb_retc( "can't read it" );
}

#pragma ENDDUMP

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 1:06 pm
by Antonio Linares
Victor,

La aplicación GetSerialDiskDemo.exe funciona bien en XP ?

En los códigos fuente que he revisado todos usan los flags FILE_SHARE_READ | FILE_SHARE_WRITE pero pudiera ser que ese flag FILE_SHARE_WRITE sea el culpable de dañar el disco duro. Ante la duda, lo quitamos y ademas faltaba la llamada a CloseHandle().

En la última versión que acabo de poner incluye estos cambios.

No puedes probar en XP en maquina virtual ? Asi te evitas el peligro de que pueda dañar el disco duro, aunque si ya no usamos FILE_SHARE_WRITE no veo como pudiese resultar dañado. Y si se dañó, lo siento de veras. Usar esta tecnología (SMART) que habla directamente con el controlador del disco es muy potente pero obviamente tiene tambien sus riesgos por lo que comentas.

Yo lo he probado en Windows 8 64 bits y funciona correctamente.

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 1:24 pm
by cuatecatl82
Fiu.. Gracias por ser tan amable de comentar Maestro..

Bueno el disco duro volvio con trabajos pero volvio, lo revise con Hirens Boot Cd y me indicaban los programas de recuperacion que mis particiones desaparecienron, volvi a reiniciar y tardo pero arranco XP, de hecho hace rato escribi desde mi movil, y ahora lo hago desde mi maquina.. No hay problema no hay de que disculparse es parte de trabajar con este tipo de funciones, se que es muy peligroso pues trabajamos a muy bajo nivel del disco duro y entiendo los riesgos, lo bueno es que pude reiniciarlo y estoy respaladando datos porque vi que quedo tocado..

Bueno a lo que vamos, el archivo GetSerialDiskDemo.exe si corre perfectamente en XP, de hecho tambien CrystalDiskInfo del cual tengo los fuentes tambien corre perfecto en XP, por eso no entiendo porque estas pruebas no dan resultados,

Voy a instalar XP en Virtual para hacer pruebas, de hecho tengo W/ corriendo en Virtual Pc, la verdad me resisto como muchos a cambiar a W7 o W8 porque es demasiado restrictivo hasta para trabajar con Fivewin..

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 1:48 pm
by Antonio Linares
Victor,

Que problemas tienes con W7 ó W8 ? Yo actualmente programo y desarrollo FWH en Windows 8 (tanto 32 bits como 64 bits) y funcionan correctamente. De hecho en mi opinión W7 es bastante mejor que XP, pues usa mucho más eficientemente la memoria.

La última versión que he publicado de la función que necesitas no debería ya ser peligrosa, de todas formas, ten la precaución de realizar tus backups y para mayor seguridad aún pruébala desde un XP virtual. En Windows 8 64 bits funciona bien.

Si otros usuarios se atreven a usarla, cuidado, no sabemos si lo que le ha ocurrido a Victor pueda estar relacionado con esta función. Asi que ojo, no vayais a estropear el arranque del disco (a nivel software). Y si a alguien le funciona bien en XP por favor que lo comente para que asi sepamos con certeza que el problema de Victor no está relacionado con el uso de esta función.

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 4:01 pm
by cuatecatl82
Después del susto he regresado a probarlo, quite las particiones de mi disco duro y las volví a crear, en una con XP y la otra con W7, el resultado funciona pero con W7 en XP solo lanza el msginfo vacío, maestro Antonio ha podido revisar los fuentes de Crystaldiskinfo que le envie? En Xp funciona bien.

W7 es muy latoso, no puedo borrar carpetas dentro de mi disco de proyectos con un simple archivo. bat siempre me sale con que necesito permisos cuando soy Administrador, quita tiempo estar abriendo programas y te ptegunte si es seguro, me estresa un tanto su entorno lo siento muy limitante.. Además de que muchos equipos no migran a W7 o W8 por lo mismo

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 4:25 pm
by Antonio Linares
Victor,

Es que los fuentes que he revisado en relación a la tecnología SMART son bastante complicados, más que nada porque es una forma de programar que principalmente usan los desarrolladores de drivers, de ahi que no me es familiar en absoluto.

Las mayoría de los fuentes estan en C++ y no permiten una portabilidad a C tal cual. Ayer hice muchas pruebas y el código que he publicado es realmente el único que he conseguido que funcione bien.

Lo has vuelto a probar en XP ? Te funciona ? Me interesa saber si funciona y si vuelve a ocurrirte algo en el disco duro, gracias

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 7:02 pm
by cnavarro
Antonio
En el hd del equipo que lo has desarrollado y probado, tienes más de una partición?

Re: Ayuda Funciones a Bajo Nivel

PostPosted: Tue Jun 10, 2014 7:46 pm
by Antonio Linares
Cristobal,

Si, pero lo que está obteniendo es el número de serie del disco (grabado en hardware), no el serial que le da Windows al formatear (grabado en software), si no me equivoco.