DLL32 function

User avatar
metaldrummer
Posts: 113
Joined: Wed Jan 10, 2007 8:43 pm
Location: Coquimbo-Chile
Contact:

DLL32 function

Post by metaldrummer »

Amigos:
Agradeceré quien me pueda orientar o indicar donde obtener información en como manejar DLL32 Function ya que necesito de ésta para poder acceder al API de Windows.
Mil gracias de antemano.
David Lagos S.
Coquimbo-Chile
www.wificafe.cl
webmaster@wificafe.cl
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

David,

A que función del API de Windows quieres acceder ?

Haz una búsqueda en estos foros por DLL AND function y te aparecerán muchos ejemplos
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
JmGarcia
Posts: 654
Joined: Mon May 29, 2006 3:14 pm
Location: Madrid - ESPAÑA

Post by JmGarcia »

En el fichero DLL.CH esta parte de lo que buscas:

Code: Select all

#xcommand DLL [<static:STATIC>] FUNCTION <FuncName>( [ <uParam1> AS <type1> ] ;
                                                     [, <uParamN> AS <typeN> ] ) ;
             AS <return> [<pascal:PASCAL>] [ FROM <SymName> ] LIB <*DllName*> ;
       => ;
          [<static>] function <FuncName>( [NOREF(<uParam1>)] [,NOREF(<uParamN>)] ) ;;
             local hDLL := If( ValType( <DllName> ) == "N", <DllName>, LoadLibrary( <(DllName)> ) ) ;;
             local uResult ;;
             local cFarProc ;;
             if Abs( hDLL ) > 32 ;;
                cFarProc = GetProcAddress( hDLL,;
                If( [ Empty( <SymName> ) == ] .t., <(FuncName)>, <SymName> ),;
                [<.pascal.>], <return> [,<type1>] [,<typeN>] ) ;;
                uResult = CallDLL( cFarProc [,<uParam1>] [,<uParamN>] ) ;;
                If( ValType( <DllName> ) == "N",, FreeLibrary( hDLL ) ) ;;
             else ;;
                MsgAlert( "Error code: " + LTrim( Str( hDLL ) ) + " loading " + ;
                If( ValType( <DllName> ) == "C", <DllName>, Str( <DllName> ) ) ) ;;
             end ;;
          return uResult

Code: Select all

#xcommand DLL32 [<static:STATIC>] FUNCTION <FuncName>( [ <uParam1> AS <type1> ] ;
                                                      [, <uParamN> AS <typeN> ] ) ;
             AS <return> [<pascal:PASCAL>] [ FROM <SymName> ] LIB <*DllName*> ;
       => ;
          [<static>] function <FuncName>( [NOREF(<uParam1>)] [,NOREF(<uParamN>)] ) ;;
             local hDLL := If( ValType( <DllName> ) == "N", <DllName>, LoadLib32( <(DllName)> ) ) ;;
             local uResult ;;
             local cFarProc ;;
             if Abs( hDLL ) <= 32 ;;
                MsgAlert( "Error code: " + LTrim( Str( hDLL ) ) + " loading " + <DllName> ) ;;
             else ;;
                cFarProc = GetProc32( hDLL,;
                If( [ Empty( <SymName> ) == ] .t., <(FuncName)>, <SymName> ),;
                [<.pascal.>], <return> [,<type1>] [,<typeN>] ) ;;
                uResult = CallDLL32( cFarProc [,<uParam1>] [,<uParamN>] ) ;;
                If( ValType( <DllName> ) == "N",, FreeLib32( hDLL ) ) ;;
             end ;;
          return uResult

#endif
Mi abuelo decía: Los aviones vuelan porque Dios quiere, y los helicópteros ni Dios sabe porque vuelan.
FWH 16.02, xHarbour 1.2.3, Harbour 3.2.0, WorkShop 4.5, AJ Make 0.30, Borlan BCC 7.00, VisualStudio 2013
User avatar
metaldrummer
Posts: 113
Joined: Wed Jan 10, 2007 8:43 pm
Location: Coquimbo-Chile
Contact:

Post by metaldrummer »

JmGarcia wrote:En el fichero DLL.CH esta parte de lo que buscas:

Code: Select all

#xcommand DLL [<static:STATIC>] FUNCTION <FuncName>( [ <uParam1> AS <type1> ] ;
                                                     [, <uParamN> AS <typeN> ] ) ;
             AS <return> [<pascal:PASCAL>] [ FROM <SymName> ] LIB <*DllName*> ;
       => ;
          [<static>] function <FuncName>( [NOREF(<uParam1>)] [,NOREF(<uParamN>)] ) ;;
             local hDLL := If( ValType( <DllName> ) == "N", <DllName>, LoadLibrary( <(DllName)> ) ) ;;
             local uResult ;;
             local cFarProc ;;
             if Abs( hDLL ) > 32 ;;
                cFarProc = GetProcAddress( hDLL,;
                If( [ Empty( <SymName> ) == ] .t., <(FuncName)>, <SymName> ),;
                [<.pascal.>], <return> [,<type1>] [,<typeN>] ) ;;
                uResult = CallDLL( cFarProc [,<uParam1>] [,<uParamN>] ) ;;
                If( ValType( <DllName> ) == "N",, FreeLibrary( hDLL ) ) ;;
             else ;;
                MsgAlert( "Error code: " + LTrim( Str( hDLL ) ) + " loading " + ;
                If( ValType( <DllName> ) == "C", <DllName>, Str( <DllName> ) ) ) ;;
             end ;;
          return uResult

Code: Select all

#xcommand DLL32 [<static:STATIC>] FUNCTION <FuncName>( [ <uParam1> AS <type1> ] ;
                                                      [, <uParamN> AS <typeN> ] ) ;
             AS <return> [<pascal:PASCAL>] [ FROM <SymName> ] LIB <*DllName*> ;
       => ;
          [<static>] function <FuncName>( [NOREF(<uParam1>)] [,NOREF(<uParamN>)] ) ;;
             local hDLL := If( ValType( <DllName> ) == "N", <DllName>, LoadLib32( <(DllName)> ) ) ;;
             local uResult ;;
             local cFarProc ;;
             if Abs( hDLL ) <= 32 ;;
                MsgAlert( "Error code: " + LTrim( Str( hDLL ) ) + " loading " + <DllName> ) ;;
             else ;;
                cFarProc = GetProc32( hDLL,;
                If( [ Empty( <SymName> ) == ] .t., <(FuncName)>, <SymName> ),;
                [<.pascal.>], <return> [,<type1>] [,<typeN>] ) ;;
                uResult = CallDLL32( cFarProc [,<uParam1>] [,<uParamN>] ) ;;
                If( ValType( <DllName> ) == "N",, FreeLib32( hDLL ) ) ;;
             end ;;
          return uResult

#endif
Gracias...esoy ya lo había visto
El tema es que no hayo como acceder a una función del api para realizar pruebas.
Estoy intentando obtener las impresoras que tengo instaladas en el pc.
Si utilizo:

aGetPrinters()

funciona ok...pero estoy intentando hacerlo de la forma difícil para poder entender como acceder a las funciones del api. Tengo instalado el sdk de windows para obtener las refencias a las funciones que necesito.

Este es el código que estoy utilizando y no me devuelve el arreglo con los datos:

Code: Select all

#include "fivewin.ch"
//#include "winspool.h"
#define PRINTER_ENUM_DEFAULT     0x00000001
#define PRINTER_ENUM_LOCAL       0x00000002
#define PRINTER_ENUM_CONNECTIONS 0x00000004
#define PRINTER_ENUM_FAVORITE    0x00000004
#define PRINTER_ENUM_NAME        0x00000008
#define PRINTER_ENUM_REMOTE      0x00000010
#define PRINTER_ENUM_SHARED      0x00000020
#define PRINTER_ENUM_NETWORK     0x00000040

FUNCTION Main()
	LOCAL pThread, aPrinters:=Array()
	IF MsgYesNo("¿Deséa mostrar las impresoras del sistema?")
		EnumPrinters(PRINTER_ENUM_NAME,,1,@aPrinters)
                aPrinters:=EnumPrinters(PRINTER_ENUM_NAME,,1)
		//aPrinters:=aGetPrinters()
		FOR n := 1 TO Len(aPrinters)
			MsgInfo(aPrinters[n])
		NEXT
	ENDIF

RETURN NIL

DLL32 FUNCTION EnumPrinters( Flags AS DWORD, Name AS LPSTR, Level AS DWORD, @aPrinters AS BYTE, cbBuf AS DWORD, @pcbNeeded AS DWORD, @pcReturned AS DWORD) ;
	AS LONG PASCAL FROM "EnumPrinters" LIB "winspool.drv"
Este es el link a la referencia del api que quiero probar para empezar a entender todo este cuento:

http://msdn2.microsoft.com/en-us/librar ... S.85).aspx


Gracias por la ayuda que me puedan brindar.
David Lagos S.
Coquimbo-Chile
www.wificafe.cl
webmaster@wificafe.cl
User avatar
metaldrummer
Posts: 113
Joined: Wed Jan 10, 2007 8:43 pm
Location: Coquimbo-Chile
Contact:

Post by metaldrummer »

Encontré un ejemplo en un foro de no se donde y funcionó lo que buscaba, pero ¿es tan complicado el poder trabajar con el api de windows?....y soy menos que novato en C++....ufff
pongo el código por si a alguien le sirve.
Ojalá alguien más aporte sobre esto...imagínense que esto es solo la punta del iceberg para mi ya que la finalidad entre otras es poder detectar cuando llega una impresión a una impresora "X", pausar la impresión y autorizar su salida en forma manual.

Code: Select all

#include "hbclass.ch"
#include "fivewin.ch"
FUNCTION Main()
	IF MsgYesNo("¿Deséa mostrar las impresoras del sistema?")
		aPrinters:=WinGetPrinters()
		Msginfo( Len(aPrinters), "Impresoras Encontradas")
		MsgInfo( WinDefaultPrinter(), "Impresora por Defecto")
		FOR n := 1 TO Len(aPrinters)
			MsgInfo(aPrinters[n])
		NEXT
	ENDIF

RETURN NIL

STATIC FUNCTION WinGetPrinters()
  LOCAL aPrn:= {}, nStart:=1, cPrinters, nStop,nPos, cPrn
  cPrinters:= ENUMPRINTERS()+';'
  nStop:= LEN(cPrinters)+1
  DO WHILE nStart< nStop
    nPos:=AT(';',cPrinters,nStart)
    IF !EMPTY(cPrn:= SUBSTR(cPrinters,nStart,nPos-nStart))
      AADD(aPrn,cPrn)
    ENDIF
    nStart:= nPos+1
  ENDDO
RETURN(aPrn)

#pragma BEGINDUMP

#undef UNICODE

#include <windows.h>
#include "hbapi.h"
#include "hbvm.h"
#include "hbstack.h"
#include "hbapiitm.h"

#define MAX_FILE_NAME 1024
#define BIG_BUFFER (1024*32)

HB_FUNC ( ENUMPRINTERS)
{
  UCHAR *Result ;
  DWORD x, Flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS  ;
  LPSTR Name = NULL ;
  DWORD Level = 5 ;
  PRINTER_INFO_5 *pPrinterEnum, *pFree;
  PRINTER_INFO_4 *pPrinterEnum4, *pFree4;
  DWORD cbBuf  ;
  DWORD BytesNeeded=0 ;
  DWORD NumOfPrinters=0 ;
  OSVERSIONINFO osvi ;  //  altered to check Windows Version
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  GetVersionEx (&osvi);
  if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
  {
    Level = 4 ;
    EnumPrinters(Flags,Name,Level,(LPBYTE) pPrinterEnum4,0,&BytesNeeded,&NumOfPrinters) ;
    if (BytesNeeded > 0)
    {
      Result = (UCHAR *)  hb_xgrab(BytesNeeded) ;
      *Result = '\0' ;
      pFree4 = pPrinterEnum4 = (PRINTER_INFO_4 *)  hb_xgrab(BytesNeeded) ;
      cbBuf = BytesNeeded ;
      if (EnumPrinters(Flags,Name,Level,(LPBYTE) pPrinterEnum4,cbBuf,&BytesNeeded,&NumOfPrinters))
      {
        for (x=0 ; x< NumOfPrinters ; x++, pPrinterEnum4++ )
        {
          strcat(Result,pPrinterEnum4->pPrinterName) ;
          strcat(Result,";") ;
        }
      }
      hb_retc(Result) ;
      hb_xfree(Result) ;
      hb_xfree(pFree4) ;
    }
    else
      hb_retc("") ;
  }
  else
   {
    EnumPrinters(Flags,Name,Level,(LPBYTE) pPrinterEnum,0,&BytesNeeded,&NumOfPrinters) ;
    if (BytesNeeded > 0)
    {
      Result = (UCHAR *)  hb_xgrab(BytesNeeded) ;
      *Result = '\0' ;
      pFree = pPrinterEnum = (PRINTER_INFO_5 *)  hb_xgrab(BytesNeeded) ;
      cbBuf = BytesNeeded ;
      if (EnumPrinters(Flags,Name,Level,(LPBYTE) pPrinterEnum,cbBuf,&BytesNeeded,&NumOfPrinters))
      {
        for (x=0 ; x< NumOfPrinters ; x++, pPrinterEnum++ )
        {
          strcat(Result,pPrinterEnum->pPrinterName) ;
          strcat(Result,";") ;
        }
      }
      hb_retc(Result) ;
      hb_xfree(Result) ;
      hb_xfree(pFree) ;
    }
    else
      hb_retc("") ;
  }
}

HB_FUNC( WINDEFAULTPRINTER )
{
  DWORD x, y ;
  UCHAR lpReturnedString[MAX_FILE_NAME] ;
  x = GetProfileString("windows","device","",lpReturnedString,MAX_FILE_NAME-1);
  y = 0 ;
  while ( y < x && lpReturnedString[y] != ',' )
    y++ ;
  hb_retclen(lpReturnedString,y) ;
}
#pragma ENDDUMP
Espero le sirva a alguien.
Saludos

P.D.: new_indika si ves esto te mande un mail a tu correo a ver si te puedo consultar algunas cosillas.
Last edited by metaldrummer on Fri Mar 28, 2008 10:14 pm, edited 1 time in total.
David Lagos S.
Coquimbo-Chile
www.wificafe.cl
webmaster@wificafe.cl
User avatar
JmGarcia
Posts: 654
Joined: Mon May 29, 2006 3:14 pm
Location: Madrid - ESPAÑA

Post by JmGarcia »

metaldrummer wrote:DLL32 FUNCTION EnumPrinters( Flags AS DWORD, Name AS LPSTR, Level AS DWORD, @aPrinters AS BYTE, cbBuf AS DWORD, @pcbNeeded AS DWORD, @pcReturned AS DWORD) ;
AS LONG PASCAL FROM "EnumPrinters" LIB "winspool.drv"
En la definicion DLL32 no tienes que poner las "arrobas" (@) solo cuando la amas a la función.
Mi abuelo decía: Los aviones vuelan porque Dios quiere, y los helicópteros ni Dios sabe porque vuelan.
FWH 16.02, xHarbour 1.2.3, Harbour 3.2.0, WorkShop 4.5, AJ Make 0.30, Borlan BCC 7.00, VisualStudio 2013
User avatar
metaldrummer
Posts: 113
Joined: Wed Jan 10, 2007 8:43 pm
Location: Coquimbo-Chile
Contact:

Post by metaldrummer »

JmGarcia wrote:
metaldrummer wrote:DLL32 FUNCTION EnumPrinters( Flags AS DWORD, Name AS LPSTR, Level AS DWORD, @aPrinters AS BYTE, cbBuf AS DWORD, @pcbNeeded AS DWORD, @pcReturned AS DWORD) ;
AS LONG PASCAL FROM "EnumPrinters" LIB "winspool.drv"
En la definicion DLL32 no tienes que poner las "arrobas" (@) solo cuando la amas a la función.
Mira:
Tengo este código:

Code: Select all

include "fivewin.ch"
#define PRINTER_ENUM_DEFAULT     0x00000001
#define PRINTER_ENUM_LOCAL       0x00000002
#define PRINTER_ENUM_CONNECTIONS 0x00000004
#define PRINTER_ENUM_FAVORITE    0x00000004
#define PRINTER_ENUM_NAME        0x00000008
#define PRINTER_ENUM_REMOTE      0x00000010
#define PRINTER_ENUM_SHARED      0x00000020
#define PRINTER_ENUM_NETWORK     0x00000040

FUNCTION Main()
   LOCAL aPrinters
   IF MsgYesNo("¿Deséa mostrar las impresoras del sistema?")
      EnumPrinters(PRINTER_ENUM_NAME,NILL,1,@aPrinters,, @nNecesitado, @nRetornado)
      FOR n := 1 TO Len(aPrinters)
         MsgInfo(aPrinters[n,1])
      NEXT
   ENDIF

RETURN NIL

DLL32 FUNCTION EnumPrinters( Flags AS DWORD, Name AS LPSTR, Level AS DWORD, aPrinters AS BYTE, cbBuf AS DWORD, pcbNeeded AS DWORD, pcReturned AS DWORD) ;
   AS BOOL PASCAL FROM "EnumPrinters" LIB "winspool.drv"
Para este código siempre me retorna aPrinters como NILL lo mismo que las otras variables por referencia ya que nNecesitado debiera devolver el número necesitado de espacio para almacenar la información en aPrinters que nunca recibe un arreglo como indica la documentación.
En qué podré estar fallando?
Saludos
David Lagos S.
Coquimbo-Chile
www.wificafe.cl
webmaster@wificafe.cl
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

David,

La función EnumPrinters() del API tiene un nivel de complejidad que dificilmente puede tratarse con el comando DLL FUNCTION desde PRG.

La función que has publicado en C, te funciona ?
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
metaldrummer
Posts: 113
Joined: Wed Jan 10, 2007 8:43 pm
Location: Coquimbo-Chile
Contact:

Post by metaldrummer »

La función EnumPrinters() del API tiene un nivel de complejidad que dificilmente puede tratarse con el comando DLL FUNCTION desde PRG.

La función que has publicado en C, te funciona ?
La función que encontré en internet que originalmente creo estaba orientada a alaska xbase++ funciona de lujo....

Mi pregunta es: porqué la DLL32 funciona en ciertas funciones y en otras no?...
Lamentablemente estoy recién comenzando a leer documentación de c++ y la verdad que soy menos que novato.
Saludos
David Lagos S.
Coquimbo-Chile
www.wificafe.cl
webmaster@wificafe.cl
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

David,

DLL FUNCTION ... permite un acceso relativamente simple a funciones que reciben unos parámetros y devuelven un resultado.

En el caso de EnumPrinters() se rellenan unas estructuras desde C, por la misma función EnumPrinters(), y hay que manejar la información de esas estructuras, desde bajo nivel.

Teoricamente se podría hacer usando DLL FUNCTION, pero puede resultar más complejo que hacerlo usando C directamente.

Estás ya familiarizado con el uso de estructuras en lenguaje C ?
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
metaldrummer
Posts: 113
Joined: Wed Jan 10, 2007 8:43 pm
Location: Coquimbo-Chile
Contact:

Post by metaldrummer »

Antonio Linares wrote:David,

DLL FUNCTION ... permite un acceso relativamente simple a funciones que reciben unos parámetros y devuelven un resultado.

En el caso de EnumPrinters() se rellenan unas estructuras desde C, por la misma función EnumPrinters(), y hay que manejar la información de esas estructuras, desde bajo nivel.

Teoricamente se podría hacer usando DLL FUNCTION, pero puede resultar más complejo que hacerlo usando C directamente.

Estás ya familiarizado con el uso de estructuras en lenguaje C ?
Estimado Antonio:
Estoy recién comenzando a leer algo de C y obviamente entiendo que su curva de aprendizaje es más lenta que otros lenguajes.
Vi que hay un DllCall de xharbour que permite llamar a las funciones del API, pero cuando intento llamar al DLL la aplicación no corre. Seguro que estoy haciendo todo o casi todo mal por mi prácticamente nulo conocimiento de C. Claro que para mí es un gran reto desarrollar esta aplicación y si esto me significa tener que aprender C y C++ GENIAL ya que es algo que he anhelado por mucho tiempo. Lo divertido es que ahora tengo que hacerlo bajo presión.
Voy a intentar leer un poco un manual que bajé de internet orientado a Borland C++ y agradeceré tu ayuda y la de cualquier colega del foro.
Yo por mi parte espero sacar adelante esto y poder desarrollar una clase que almacene todo este know how
Un abrazo y agradezo cualquier ayuda
David Lagos S.
Coquimbo-Chile
www.wificafe.cl
webmaster@wificafe.cl
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

David,

El lenguaje C es realmente simple. De ahí radica su potencia y su belleza.

Fué diseñado para programar el sistema operativo Unix (padre de Linux, Mac, etc.), y se convirtió de "facto" en el lenguaje ideal para desarrollar los sistemas operativos. Por ejemplo, decidimos usar el lenguaje C para construir Harbour, para así obtener la máxima potencia y tener un control total :-)

Hace exactamente lo que se le dice. Si se le dice algo mal, él lo hace mal. Es decir, no hace cosas por "su cuenta". Es un robot que nos obedece en todo. Y por otra parte está tan cercano a la máquina, que en realidad es "generar" ensamblador, usando un lenguaje y "lógica" a nivel humano.

Haz todas las preguntas que quieras aqui, que con mucho gusto te ayudaremos a que te "enamores" de él :-) y de paso le servirá a más compañeros.
regards, saludos

Antonio Linares
www.fivetechsoft.com
ARCC
Posts: 86
Joined: Sat Jun 24, 2006 4:27 pm
Location: Maracaibo - Zulia - Venezuela
Contact:

Post by ARCC »

Buen día para todos...

Que tal David y Antonio, disculpen que les realice esta pregunta la cual no está directamente asociada a la prengunta inicial, pero la cual creo que nos va a beneficiar a todos.

Al igual que David estoy incursionando en lenguaje C, y aunque tengo muy poca experiencia porque en la universidad vi lenguaje C versión 1.0, pero fue hace mucho tiempo y no recuerdo mucho.

La pregunta es: Antonio ya que debemos aprender lenguaje C para aplicarlo a [x]Harbour que versión nos recomiendas o se aplica a [x]Harbour?, porque existen muchas versiones de C (C, C++, C#, Visual C, etc.) y como debemos aprender y para no perder mucho tiempo, nos enfocariamos solo en aprender la versión que necesitamos. De antemano muchas gracias
Saludos,

Antonio Castro
Maracaibo - Venezuela
ant_cas@yahoo.com
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Lenguaje C solamente. Ni C++, ni C#, ni Visual C.
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
metaldrummer
Posts: 113
Joined: Wed Jan 10, 2007 8:43 pm
Location: Coquimbo-Chile
Contact:

Post by metaldrummer »

Antonio:
Mil gracias por tus respuestas. Si no me equivoco C++ es simplemente C con soporte de Clases, correcto?
Si es así, me debiera servir el libro "Teach Yourselve Borland C++ in 14 days"?. Obviamente sin aplicar la parte de objetos y ya que utilizo borland c++ 5.51 como compilador.
Nuevamente mil gracias por tu ayuda desinteresada.
Saludos
David Lagos S.
Coquimbo-Chile
www.wificafe.cl
webmaster@wificafe.cl
Post Reply