Formatowanie każdego elementu tablicy na format 02X

0

Hej! Mam pewien problemik z formatowaniem... Może to dla niektórych będzie banał...
Chodzi o przeformatowanie każdego elementu tablicy i ostatecznie zwrócenie w funkcji unsigned char*

 
unsigned char* returnHexStringWithoutSpaces(LPBYTE baData, DWORD dataLen)
{
	unsigned int x = 0;
	int iRozmiar = 0;


	for(x = 0; x < dataLen; x++)		
	{
		iRozmiar++;
	}


	unsigned char *chWynik2 = new unsigned char[iRozmiar];
	for(i = 0; i < dataLen;i++)		
	{
		
		printf("%02X",baData[i]);
		chWynik2[i] = baData[i];
	}



	return chWynik2;



}

Każdy element tablicy mogę wyświetlać bez problemu w wybranym formacie, tylko chodzi mi o to, żeby każdy element przeformatować i go zmodyfikować i zwrócić jako unsigned char*
Czy może stworzyć zmienną tymczasową i odczytać element tablicy, skopiować do zmiennej tymczasowej, przeformatować i z powrotem przypisać element tablicy?

Program zwraca taki wynik:
W pętli funkcji po formatowaniu
03907BC8

Wartość zwrócona przez funkcję:
3907bc8

Jak można przeformatować każdy element tablicy unsigned char wg wzorca 02X ?

W C# napisałem coś podobnego (wrapper pewnej funkcji WinAPI), i od razu zwracam sformatowany string,a tutaj jest problem...

0

Użyj funkcji sprintf. Pamiętaj, że wynikowy bufor musi mieć rozmiar dataLen*2+1 (każdy bajt zapisywany jest przez dwie cyfry szesnastkowe, do tego terminating null stringa). Niepotrzebnie również robisz tę pętlę do przypisania iRozmiar - DWORD to zwykły unsigned int, więc możesz zrobić po prostu:

unsigned int iRozmiar = dataLen;
0
  1. Co przesyłasz do funkcji? Czym jest typ LPBYTE?
  2. Po co ta pętla for na początku, skoro przesyłasz wprost dataLen (długość zmiennej typu LPBYTE? ilość znaków w tablicy?) iRozmiar = dataLen-1 wg Twojego kodu, ale zastanów się czy nie powinno być iRozmiar = dataLen;
  3. LPBYTE baData przesyłane do funkcji nie powinno być wskaźnikiem? (jeśli chcesz działać jak na tablicy?)
  4. Zwracając jako return chWynik2 - zwracasz wartość, którą przechowuje wskaźnik, czyli adres elementu na który wskazuje.
  5. A jeśli chodzi o konwersje to może to Ci pomoże: http://stackoverflow.com/questions/23487485/02x-format-specifier-for-char-array
    (nie bardzo rozumiem co Twój kod ma robić).
0

Funkcja to tak na prawdę zwraca nr karty (UID) MIFARE.
PCSC_Exchange(baCmdApduGetData,(DWORD)sizeof(baCmdApduGetData),baResponseApdu, &lResponseApduLen);
czyli de facto:

LONG PCSC_Exchange(LPCBYTE pbSendBuffer ,DWORD  cbSendLength ,LPBYTE  pbRecvBuffer ,LPDWORD pcbRecvLength )
{	
	
	LPCSCARD_IO_REQUEST  ioRequest;
	LONG	 lRetValue;

	switch (m_dwActiveProtocol)
	{
		case SCARD_PROTOCOL_T0:
			ioRequest = SCARD_PCI_T0;
			break;

		case SCARD_PROTOCOL_T1:
			ioRequest = SCARD_PCI_T1;
			break;

		default:
			ioRequest = SCARD_PCI_RAW;
			break;
	}
	
	*pcbRecvLength = RcvLenMax;


	lRetValue = SCardTransmit(m_hCard,		
							ioRequest,		
							pbSendBuffer,	
							cbSendLength,	
							NULL,			
							pbRecvBuffer,	
							pcbRecvLength);	


	return lRetValue;		
}
 

Ostatecznie ta moja funkcja zwraca *unsigend char i jest eksport tej funkcji z DLLki...

Spróbuje z sprinf...

unsigned char *chWynik2 = new unsigned char[iRozmiar];
for(i = 0; i < dataLen;i++)		
{
	


	printf("[%02X]",baData[i]);
	chWynik2[i] = baData[i];
	sprintf(chWynik2[i], "%02X");
	printf("[%02X]",chWynik2[i]);
}

Aczkolwiek, rzuca mi błąd:

Error	1	error C2664: 'sprintf' : cannot convert parameter 1 from 'unsigned char' to 'char *'
 

Rzutowanie (char*) powoduje wieszanie się programu przy sprintf...

1

sprintf oczekuje wskaźnika na C-string i "standardowo" przyjmuje taki zapis:

char foo[64];
sprintf(foo, ...);

Ponieważ tablica jest tak na prawdę wskaźnikiem na jej pierwszy element. Gdy używasz operatora [ ] wyłuskujesz konkretny element z tablicy, który to już jest zmienną, nie wskaźnikiem. Dlatego musisz użyć operatora referencji:

sprintf(&chWynik2[i], ...);

Dzięki czemu przekażesz wskaźnik do wybranego elementu w tablicy charów. Operujesz na ucharach, więc musisz jeszcze rzutować ten wskaźnik:

sprintf((char*)&chWynik2[i], ...);

Nadal masz ten problem o którym wspomniałem wcześniej. Format 02X zajmie 2 bajty w stringu wyjściowym na każdy bajt danych wejściowych, a przy Twojej indeksacji otrzymasz tylko po jednej cyfrze z każdego bajtu.
Na wejściu masz bajty: 220 (0xDC), 78 (0x4E), 123 (0x7B)
String wyjściowy będzie wyglądał po kolejnych przebiegach tak:

  1. DC
  2. D4E
  3. D47B
    Dlatego indeksy musisz wyliczać w taki sposób:
unsigned char* result = new unsigned char[dataLen*2+1];
for(int i = 0; i < dataLen; i++)
    sprintf((char*)&result[i*2], "%02X", inputBytes[i]);
return result;

+1 w *result *ponieważ na końcu stringa musi być jeszcze bajt o zerowej wartości, inaczej będziesz miał problemy przy wyświetlaniu tego stringa, porównywaniu go poprzez strcmp i inne, a wręcz samo sprintf może wywołać nieprawidłową operację, ponieważ automatycznie dopisuje ten zerowy bajt na końcu. Dlatego wywołując tę pętlę z i == 3 (z danymi wejściowymi jak wyżej) przypisywane są takie wartości: result[4] = '7', result[5] = 'B', result[6] = '\0'

Pamiętaj też, że dane otrzymane z tej funkcji musisz gdzieś później ręcznie zwolnić, tj.:

unsigned char* hexString = returnHexStringWithoutSpaces...
//...operacje na hexString...
delete [] hexString;
0

Wielkie dzięki! Teraz jeszcze muszę przerobić kod...
Tak na prawdę ta funkcja jest używana już przy jako return przy wyjściu z innej funkcji, która powoduje zwrócenie tej wartości sformatowanej na zewnątrz DLL.
A co to jest w tym kodzie inputBytes ?

Kurcze, ale funkcja printf bez problemu radzi sobie z wyświetlaniem każdego elementu tablicy *char...

W C# nie było takich problemów, zrobiłem tak:

            retval = HID.SCardTransmit(hCard, ref sioreq, sendBuffer, sendbufferlen, ref rioreq, receiveBuffer, ref receivebufferlen);
            if (retval == 0)
            {
                if ((receiveBuffer[receivebufferlen - 2] == 0x90) && (receiveBuffer[receivebufferlen - 1] == 0))
                {
                    StringBuilder hex1 = new StringBuilder((receivebufferlen - 2) * 2);
                    foreach (byte b in receiveBuffer)
                        hex1.AppendFormat("{0:X2}", b);
                    uid_temp = hex1.ToString();
                    uid_temp = uid_temp.Substring(0, ((int)(receivebufferlen - 2)) * 2);
                }
 

no i później

                s = "";
                for (int k = 0; k <= ((receivebufferlen - 2) * 2 - 1); k += 2)
                {
                    s = s + uid_temp.Substring(k, 2) + " ";
                }
                uid_temp = s;
                UID_KARTY = uid_temp.Replace(" ", "");
            }
 

no i ten UID_KARTY to to samo co chce osiągnąć tutaj w języku C/C++, czyli w tablicy znaków string sformatowany już szesnastkowo.

Chyba,że może inaczej można przekazać stringa z natywnej DLL do aplikacji tworzonej w Delphi XE (może typ BSTR?).

0

inputBytes to Twoje baData, wybacz za zamieszanie. :P printf puszcza wynik bezpośrednio na wyjście znak po znaku lub tworzy ten zerowy bajt wewnętrznie w buforze, dlatego wyświetlanie działa out-of-the-box.

Co do integracji z Delphi niestety nie pomogę, gdyż nie mam na tym polu doświadczenia.

0
  1. Pętla for żeby instrumentować zmienną o jeden? Troszkę wiecej myślenia podczas pisania kodu.
  2. google. Takie coś znajdziesz bez problemu. Umiejętność szukania rozwiązań jest bardzo ważna.
  3. twój problem jest prosty http://ideone.com/w0Plvi
0

hmm wynik działania DLLki jest taki:
Card Serial Number (UID): 02907BC8
baData[02]result[30]
baData[90]result[39]
baData[7B]result[37]
baData[C8]result[43]

A program tak odczytuje:

JESTESMY W EXE, WYNIK DZIALANIA BIBLIOTEKI DLL:
[0][9][7][C]

Kod biblioteki DLL (fragment):

	unsigned char *chWynik2 = new unsigned char[iRozmiar];

	
	unsigned char* result = new unsigned char[dataLen*2+1];

	for(i = 0; i < dataLen;i++)		
	{
		


		printf("baData[%02X]",baData[i]);
		//chWynik2[i] = baData[i];
		sprintf((char*)&result[i], "%02X", baData[i]);
		printf("result[%02X] \n", result[i]);
		chWynik2[i] = result[i];

	}


	return chWynik2;
 

Kod programu:

unsigned char *chWynik;


HINSTANCE hDll;
hDll = LoadLibrary( L"SmartCardLib" );

if( hDll != NULL )
{
    pobierz_UID_Karty_MIFARE =( MYPROC ) GetProcAddress( hDll, "pobierz_UID_Karty_MIFARE" );
   std::cout << "Szukamy funkcji " << std::endl;
    if( pobierz_UID_Karty_MIFARE != NULL )
    {
		chWynik = ( pobierz_UID_Karty_MIFARE )(  );

		std::cout << "JESTESMY W EXE, WYNIK DZIALANIA BIBLIOTEKI DLL: \n";
	   for(int i = 0; i < sizeof(chWynik);i++)		
		{
			printf("[%c]",chWynik[i]);
		}
	   std::cout <<  std::endl;
	   printf("printf\n");

	   std::system("pause");


    }
	


    FreeLibrary( hDll ); 

Już całkiem się pogubiłem. Może przekazać tablicę bajtów bez tego zera na początku (bo tak przekazuje pierwotnie) a niech sobie Ci co chcą skorzystać sami sformatują (czy to w C# co mi się udaje bez problemów) czy w Delphi (firma zewnętrzna, której to potrzebne).

1

Namieszałeś kompletnie w tej swojej funkcji i masz wynik taki, jaki zasymulowałem w poprzednim poście. Wycina Ci z każdego bajtu jedną cyfrę. Nadal masz ten źle indeksowany chWynik2, który zwracasz z funkcji.

printf("result[%02X] \n", result[i]);

Tu też namieszałeś, ponieważ teraz zamieniasz bajt z kodem ASCII reprezentującym cyfrę szesnastkową z inputu na reprezentację szesnastkową tego bajtu, czyli... dwukrotnie wykonujesz tę operację. Zrób tę funkcję tak:

unsigned char* twojaFunkcja(LPBYTE inputBytes, DWORD dataLen)
{
    unsigned char* result = new unsigned char[dataLen*2+1];
    for(int i = 0; i < dataLen; i++)
        sprintf((char*)&result[i*2], "%02X", inputBytes[i]);
    return result;
}

Jeśli chcesz podejrzeć wynik, dodaj przed return result;:

printf("%s", (char*)result);
0

Ufff działa :) dzięki :)
Ile to człowiek jeszcze musi się uczyć :) No ciekawe czy w Delphi sobie odtworzą to, ale z tego co pamiętam był tam typ PChar :)

W programie po prostu wyświetlam sobie:

 
unsigned char *chWynik;


HINSTANCE hDll;
hDll = LoadLibrary( L"SmartCardLib" );

if( hDll != NULL )
{
    pobierz_UID_Karty_MIFARE =( MYPROC ) GetProcAddress( hDll, "pobierz_UID_Karty_MIFARE" );
   std::cout << "Szukamy funkcji w DLL... " << std::endl;
    if( pobierz_UID_Karty_MIFARE != NULL )
    {
	chWynik = ( pobierz_UID_Karty_MIFARE )(  );
	printf("OK \n");
	printf("Pobrany nr UID karty z funkcji w bibliotece DLL: \n");
	printf("%s", (char*)chWynik);
	getchar();

    }
	
    FreeLibrary( hDll );
}

No i dalej już ten nr karty jest konwertowany przez funkcję zawartą w bazie danych na nr ID pracownika (identyfikator)... itp...
:-)
Chyba muszę sobie przypomnieć/przeczytać niektóre rozdziały Symfonii C++ J. Grębosza :-)

0

A jeszcze pytanko mam... zwrócić z takiej funkcji samo 0?
czy bezpieczniej jest NULL ?
Z NULL jest najłatwiej bo działa, sprawdzałem..
Tak żeby to było uniwersalne i z tej DLLki mogły rózne środowiska skorzystać?
(chodzi o przypadek kiedy karty nie ma w czytniku) ?

1

0 i NULL (na poziomie binarnym) to to samo.

0

Hah no tak!
:-D
Git...
Pozostało jeszcze rozprawić się z wyciekiem pamięci... bo w sumie jak zwracam dynamiczną tablicę to jak ją usunąć? Skoro robię return i już nie zrobie delete...
Tutaj nie ma Garbage Collectora :D

Mała aktualizacja kodu:

unsigned char* returnHexStringWithoutSpaces(LPBYTE baData, DWORD dataLen)
{

	const size_t alloc_size = 128; 
	STRSAFE_LPSTR resultsafe = NULL;
	STRSAFE_LPCSTR result = new TCHAR[dataLen*2+1];

	for(unsigned int i = 0; i < dataLen;i++)		
	{
		for(unsigned int i = 0; i < dataLen; i++)
			sprintf_s((char*)&result[i*2], sizeof((char*)&result[i*2]),"%02X", baData[i]);
	}
    resultsafe=(STRSAFE_LPSTR)CoTaskMemAlloc(alloc_size); 
    StringCchCopyA ( resultsafe, alloc_size, result ); 
	// sprzątamy po sobie, zwalniamy pamięć, tutaj nie ma GC
	delete result;
	    return (unsigned char*)resultsafe;

}
 

Gdzieś w kodzie DLL funkcji pobierz_UID_Karty_MIFARE(void) która jest wywoływana przez inny program:

	return
		returnHexStringWithoutSpaces(baResponseApdu, lResponseApduLen - 2);
 

Prototyp funkcji w DLL

extern "C" SMARTCARDLIB_API unsigned char* pobierz_UID_Karty_MIFARE(void);
 

Czy teraz nie ma wycieków pamięci? Usuwam oryginalnego ciąg znaków, wcześniej inicjalizując CoTaskMemAlloc, kopiując go do STRSAFE_LPSTR funkcją StringCchCopyA i ostatecznie zwracając STRSAFE_LPSTR?

0

Mała aktualizacja kodu: (...)

Lubisz komplikować rzeczy proste ;) Po co ten new? Nie możesz od razu przydzielić sobie pamięci funkcją CoTaskMemAlloc?

Czy teraz nie ma wycieków pamięci?

Przecież to, czy jest wyciek czy nie, zależy od tego, jak użyjesz tej swojej funkcji.

Jeśli tak:

{
    unsigned char* res = returnHexStringWithoutSpaces(...);
    ...
}

To masz wyciek. A jeśli w ten sposób:

{
    unsigned char* res = returnHexStringWithoutSpaces(...);
    ...
    CoTaskMemFree(res);
}

to nie masz wycieku.

Według mnie ta funkcja nie powinna zwracać nowej pamięci, tylko wpisywać do bufora podanego w parametrze.

0

Hmm czyli najlepiej będzie po prostu faktycznie przerobić tą funkcje, że kod karty zwracany jest w argumencie funkcji...
Bo nie zadeklarować tablicy statycznej jako wartość zwracaną w funkcji (chodzi mi o C i WinAPI) ?

0

Zmienna statyczna, podobnie jak globalna, w tym przypadku to niezbyt dobry pomysł.

0

No dobra, bufor sam sobie ustalam w DLL. Chcę to przez parametr przekazać ten nr karty. Zmodyfikowałem kod, kod programu, który czyta tą bibliotekę ale oczywiście się wysypuje. Teraz kod wygląda tak:

W bibliotece DLL:


SMARTCARDLIB_API int pobierz_UID_Karty_MIFARE(unsigned char *uid)
{
// tutaj lecą funkcje związane z czytnikiem,sterownikiem itp
//....

    PCSC_Exchange(baCmdApduGetData,(DWORD)sizeof(baCmdApduGetData),baResponseApdu, &lResponseApduLen);
	PCSC_EXIT_ON_ERROR(lRetValue);
/// dalej coś tam z czytnikiem funkcje itp.

	unsigned char* result = new unsigned char[lResponseApduLen];
	for(unsigned int i = 0; i < lResponseApduLen;i++)		
	{
		for(unsigned int i = 0; i < lResponseApduLen; i++)
		{
			sprintf_s((char*)&result[i*2], sizeof((char*)&result[i*2]),"%02X", baResponseApdu[i]);
		}
	}
    
	StringCchCopyA((char*)uid, lResponseApduLen*2+1, (char*)result);
	*uid=*uid;
	return 0;
 

A kod programu, który czyta DLL

int _tmain(int argc, _TCHAR* argv[])
{

unsigned char chWynik = NULL;
HINSTANCE hDll; 
hDll = LoadLibrary( L"SmartCardLib" );

if( hDll != NULL )
{
    pobierz_UID_Karty_MIFARE =( MYFUNC ) GetProcAddress( hDll, "pobierz_UID_Karty_MIFARE" );
    printf("Szukamy funkcji w DLL... ");
    if( pobierz_UID_Karty_MIFARE(&chWynik) == 0 )
    {
		printf("OK \n");
		printf("Pobrany nr UID karty z funkcji w bibliotece DLL: \n");
		printf("%s", (char*)chWynik);
		printf("\n");
		if ( (chWynik == NULL) || (chWynik == NULL))
		{
			printf("BRAK KARTY LUB INNY PROBLEM! \n");
		}

    }
	else
	{
		printf("Brak takiej funkcji w pliku DLL! \n");
	}
	
	getchar();

    FreeLibrary( hDll );
}


}
 

i nagłówek programu

typedef  int ( * MYFUNC )( unsigned char* );
MYFUNC pobierz_UID_Karty_MIFARE; 

Tylko się wiesza przy wywoływaniu funkcji... DLL wczytuje...
Ja myślałem, że przekazywanie przez parametr jakiejś wartości to proste jak z var w Delphi albo out w C#

Czy może źle zadeklarowałem funkcję tą która ma być eksportowana....

0

Kolega chyba wskaźników nie zna ;)

Pisałem, że ten new jest zbędny:

SMARTCARDLIB_API int pobierz_UID_Karty_MIFARE(char *uid)
{
	...
	
	/// dalej coś tam z czytnikiem funkcje itp.

	
	int j = 0;
	
	for(unsigned int i = 0; i < lResponseApduLen; i++, j += 2)
	{
		sprintf_s((char*)(uid + j), 2,"%02X", baResponseApdu[i]);
	}
	
	uid[j] = '\0';
	
    return 0;
}
char chWynik[14 + 1]; // zakładam, że UID nie będzie miał więcej niż 7 bajtów, czyli 14 + 1 w hex

if( pobierz_UID_Karty_MIFARE(chWynik) == 0 ) { ... }

Tu wersja bez sprintf:

	int j = 0;
	const char* hex = "0123456789ABCDEF";
	
	for(unsigned int i = 0; i < lResponseApduLen; i++)
	{
		uid[j++] = hex[ (baResponseApdu[i] >> 4) & 0xF ];
		uid[j++] = hex[ baResponseApdu[i] & 0xF ];
	}
	
	uid[j] = '\0';
0

Przerobiłem kod, kompiluje się... ale wyrzuca mi przy wywołaniu funkcji:
0xC0000005: Access violation reading location 0x00000000.
Nie wchodzi mi nawet w początek funkcji, bo robie prosty printf...
Może źle zadeklarowałem w programie testowym nagłówek funkcji?
Bo wyszukiwać to ją wyszukuje...

Chyba wiem... może coś w stylu CALLBACK* dodać w deklaracji funkcji w programie?

0

Daj __stdcall, tak jak pokazałem Ci we wczorajszym komentarzu.

0

Dodałem __stdcall ale funkcja się nie wczytuje. Sprawdziłem Dependency Walkerem, funkcja jest na liście eksportowanych funkcji...

Kod w DLL


#ifdef SMARTCARDLIB_EXPORTS
#define SMARTCARDLIB_API __declspec(dllexport)
#else
#define SMARTCARDLIB_API __declspec(dllimport)
#endif



extern "C" SMARTCARDLIB_API int __stdcall pobierz_UID_Karty_MIFARE(char *uid);
 

no i właściwa funkcja:

SMARTCARDLIB_API int __stdcall pobierz_UID_Karty_MIFARE(unsigned char *uid)
{
// kod funkcji
}

Program korzystający z DLL.
Nagłówek:

 
#include "stdafx.h"

typedef int (__stdcall * MYFUNC )( unsigned char* );

MYFUNC pobierz_UID_Karty_MIFARE;

Kod programu:

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <conio.h>
#include <Objbase.h>
#include <string>
#include "SmartCardLib_Test.h"



int _tmain(int argc, _TCHAR* argv[])
{

unsigned char chWynik[14 + 1]; 
HINSTANCE hDll; 
hDll = LoadLibrary( L"SmartCardLib" );

if( hDll != NULL )
{
    pobierz_UID_Karty_MIFARE = ( MYFUNC ) GetProcAddress( hDll, "pobierz_UID_Karty_MIFARE" );
    printf("Szukamy funkcji w DLL... \n");
	if (pobierz_UID_Karty_MIFARE == NULL)
	{
		printf("Nie mogę odnaleźć funkcji! \n");
		getchar();
		return -1;
	}

    if( pobierz_UID_Karty_MIFARE(chWynik) == 0 )
    {
		//chWynik = pobierz_UID_Karty_MIFARE();
		printf("OK \n");
		printf("Pobrany nr UID karty z funkcji w bibliotece DLL: \n");
		printf("%s", (char*)chWynik);
		printf("\n");

    }
	else
	{
		printf("Brak takiej funkcji w pliku DLL! \n");
	}
	
	getchar();

    FreeLibrary( hDll );
}



}

 

No i niestety pobierz_UID_Karty_MIFARE zwraca NULL. :-(

1

Dlaczego parametr funkcji pobierz_UID_Karty_MIFARE w deklaracji jest typu char*, a w definicji unsigned char*?

Pokaż kod funkcji, bo trudno powiedzieć, co może być nie tak.

0

Oj poprawiłem już na unsigend.
Ten sam kod funkcji wykonałem jako funkcja bez parametrów i działa (wyniki wyświetlam na konsoli).
Kod funkcji

 
extern "C" SMARTCARDLIB_API int __stdcall pobierz_UID_Karty_MIFARE(unsigned char *uid);
#include "stdafx.h"
#include <sstream>
#include <stdlib.h>
#include <Math.h>
#include <string>
#include <strsafe.h>
#include "SmartCardLib.h"
#include "winscard.h"
#include "pcsc.h"
#include "util.h"
#include "ClassCardType.h"

#pragma comment(lib, "Winscard.lib")


SMARTCARDLIB_API int __stdcall pobierz_UID_Karty_MIFARE(unsigned char *uid)
{
	printf("Jestesmy w funkcji... \n");
    // Get Data: CLA = 0xFF, INS = 0xCA, P1 = 0x00, P2 = 0x00, Le = 0x00
    BYTE baCmdApduGetData[] = { 0xFF, 0xCA, 0x00, 0x00, 0x00};

    BYTE baResponseApdu[300];	
	DWORD lResponseApduLen = 0;

    BYTE atr[40];
	INT	 atrLength;
	LONG lRetValue;


	// PCSC_Connect - true - szukamy czytnika bezstykowego = -CL czyli contact less
	lRetValue = PCSC_Connect(NULL, TRUE );
    PCSC_EXIT_ON_ERROR(lRetValue);
    
    lRetValue = PCSC_WaitForCardPresent();


	if (lRetValue == 0x02)
	{

		//PCSC_Disconnect();

		return -1 ;// błąd
	}

    PCSC_EXIT_ON_ERROR(lRetValue);



    lRetValue = PCSC_ActivateCard();
    PCSC_EXIT_ON_ERROR(lRetValue);
    
    lRetValue = PCSC_GetAtrString(atr, &atrLength);
    PCSC_EXIT_ON_ERROR(lRetValue);

    PCSC_Exchange(baCmdApduGetData,(DWORD)sizeof(baCmdApduGetData),baResponseApdu, &lResponseApduLen);
	PCSC_EXIT_ON_ERROR(lRetValue);
    

    if( baResponseApdu[lResponseApduLen - 2] == 0x90 &&
        baResponseApdu[lResponseApduLen - 1] == 0x00)
    {

	    
		if( getClessCardType(atr) == Mifare1K)
	    {
            //printf("Card Type: MIFARE Classic 1k");
	    }
	    else if( getClessCardType(atr) == Mifare4K)
	    {
		    //printf("Card Type: MIFARE Classic 4k");
	    }
	    else if( getClessCardType(atr) == MifareUL)
	    {
		    //printf("Card Type: MIFARE Ultralight");
	    }
    }

    //lRetValue = PCSC_WaitForCardRemoval();

    PCSC_Disconnect();
    		printf("%i\n", lResponseApduLen);

    int j = 0;
 
    for(unsigned int i = 0; i < lResponseApduLen; i++, j += 2)
    {
        sprintf_s((char*)(uid + j), 2,"%02X", baResponseApdu[i]);
    }
 
    uid[j] = '\0';
 
    return 0;


}
 

Nie wyświetla mi nawet tego tekstu na konsoli,ze jestesmy w funkcji...
UPDATE.
Wyrzuciłem __stdcall z deklaracji. Wczytuje funkcję, wiesza się w 1 iteracji pętli tzn
sprintf_s((char*)(uid + j), 2,"%02X", baResponseApdu[i]);

Dobra, zrobiłem wersję nie z sprinf_s tylko bez...

 
int j = 0;
    const char* hex = "0123456789ABCDEF";
 
    for(unsigned int i = 0; i < lResponseApduLen-2; i++)
    {
        uid[j++] = hex[ (baResponseApdu[i] >> 4) & 0xF ];
        uid[j++] = hex[ baResponseApdu[i] & 0xF ];
    }
 
    uid[j] = '\0';

A w programie:

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <conio.h>
#include <Objbase.h>
#include <string>
#include "SmartCardLib_Test.h"



int _tmain(int argc, _TCHAR* argv[])
{

unsigned char chWynik[14 + 1]; 

HINSTANCE hDll; 



hDll = LoadLibrary( L"SmartCardLib" );

if( hDll != NULL )
{
    pobierz_UID_Karty_MIFARE = ( MYFUNC ) GetProcAddress( hDll, "pobierz_UID_Karty_MIFARE" );
    printf("Szukamy funkcji w DLL... \n");
	if (pobierz_UID_Karty_MIFARE == NULL)
	{
		printf("Nie mogę odnaleźć funkcji! \n");
		getchar();
		return -1;
	}

    if( pobierz_UID_Karty_MIFARE(chWynik) == 0 )
    {
		printf("OK \n");
		printf("Pobrany nr UID karty z funkcji w bibliotece DLL: \n");
		printf("%s", (char*)chWynik);
		printf("\n");

    }
	else
	{
		printf("Brak takiej funkcji w pliku DLL! \n");
	}
	
	getchar();

    FreeLibrary( hDll );
}



 

Także działa już. Nie wiem czemu wersja z sprintf_s nie działa...
Z czystej ciekawości, jak tablice najlepiej przekazywać napisy *char do parametru wyjściowego funkcji ?
Jeśli tworzymy funkcje np. pobierzNapis(char * napis), żeby "wypełnić" parametr napis?

1

Wersja ze sprintf_s nie działała, bo zrobiłem mały błąd polegający na tym, że nie uwzględniłem null-terminatora i podałem w drugim parametrze wartość 2 zamiast 3. Funkcja rzuca wyjątek jeśli bufor jest za mały - a jest od samego początku - i stąd brak danych w buforze.

0

Aaa tak myślałem no tak :)
To z której wersji lepiej korzystać?
Poprawiłem:

SMARTCARDLIB_API int pobierz_UID_Karty_MIFARE(unsigned char *uid)
{
// jakiś kod
	unsigned char* result = new unsigned char[(lResponseApduLen-2)*2+1];
    for(unsigned int i = 0; i < lResponseApduLen-2;i++)        
    {
        for(unsigned int i = 0; i < lResponseApduLen-2; i++)
            sprintf_s((char*)&result[i*2], sizeof((char*)&result[i*2]),"%02X", baResponseApdu[i]);
    }
	printf("%s", (char*)result);

	strcpy((char*)uid, (char*)result);
	delete result;


 return 0;
}



 

Działa. Teraz już nie będzie wycieków pamięci? Kopiuje tablicę na parametry i z programu odczytuje, a to co utworzyłem new pod koniec kasuje.
P.S. Jak użyć funkcji strcpy_s ?
Używam strcpy_s((char*)uid, sizeof((char*)result), (char*)result);
no i niestety sie wywala :/ strcpy działa ok

0

Jaki jest sens tworzenia bufora result, jeśli możesz od razu wpisywać do uid (tak jak pokazałem to wcześniej)? Jesteś w stanie podać jakiś racjonalny powód?

sizeof((char*)&result[i*2])

A cóż to za diabelstwo?! Tam powinieneś podać rozmiar bufora, a nie wielkość wskaźnika char*. Wpisz po prostu wartość 3 ;)

0

Hmm a ten bufor to jak się ustala?? czy to ma być z "zapasem" ?

1

Masz format-string, z którego wynika, że sprintf ma wypluwać dwuznakowe hexy, więc 2 znaki plus null-terminator daje 3. Jasne?

Odpowiedz na moje pytanie odnośnie użycia new.

1 użytkowników online, w tym zalogowanych: 0, gości: 1