Buonasera.
Dopo tutto questo tempo sono riuscito a mettere insieme quel che mi serviva per realizzare e provare il programma che avevo in mente. Come promesso, ammesso che a qualcuno possa interessare, riporto qui il codice del file che si occupa del riconoscimento della postazione PC e dell'individuazione del file dei dati contenente l'elenco formattato dei programmi da lanciare e dei documenti da aprire in relazione a quella postazione.
#include "gestione_mac_address.h"
#include <stdio.h>
#include <string.h>
typedef struct {
char nome[MAX_ADAPTER_NAME_LENGTH+4]; // nome dell'adapter
char desc[MAX_ADAPTER_DESCRIPTION_LENGTH+4]; // descrizione dell'adapter
BYTE mcAd[MAX_ADAPTER_ADDRESS_LENGTH]; // Mac Address dell'adapter
UINT lMca; // lunghezza di mcAd
} Adapter_t;
typedef struct {
Adapter_t adpt; // dati dell'adapter
char file[_MAX_FNAME]; // nome del file abbinato
} Abbinamento_t;
#define MAX_MCADDDFLT 16 // dovrebbero essere piu' che sufficienti, ma
// caso mai non bastassero e' previsto un meccanismo
// dinamico per l'allocazione di un buffer di
// dimensioni adeguate
static Abbinamento_t *carica_file_abbinamenti( FILE *fSrc, UI*qAbbinamenti );
static Adapter_t *rileva_adapter_correnti( UI*qAdapter );
/*==============================================================================
Restituisce in nfd (che deve avere dimensioni almeno pari a _MAX_PATH char) il
nome del file abbinato alla postazione PC identificata tramite i mac address
degli adapter installati. L'abbinamento viene identificato basandosi sul
contenuto di un file di riferimento precedentemente compilato con i dati
necessari.
==============================================================================*/
int nome_file_dati_da_mac_address( char *nfd ) {
UI qAbb, iAbb; // qAbb: quantita' abbinamenti
UI qAdp, iAdp; // qAdp: quantita' degli adapter correnti
Abbinamento_t *ab = NULL;
Adapter_t *ad = NULL;
int err = kCodErrNullPtr;
if( NULL != nfd ) {
FILE *f = NULL;
char nfa[_MAX_PATH]; // nfa: nome file abbinamenti
_makepath( nfa, NULL, kStrCartellaAutoaperturaFile,
kStrFileAbbinamentoDati, kStrEstFileAbbinamentoDati );
f = fopen( nfa, "r" );
if( !f ) { err = kCodErrNoFileDatiPC; goto uscita; }
ab = carica_file_abbinamenti( f, &qAbb );
fclose( f ); f = NULL; // non serve piu'
if( !ab ) { err = kCodErrDatiPCNonValidi; goto uscita; }
ad = rileva_adapter_correnti( &qAdp );
if( !ad ) { err = kCodErrNoAdapter; goto uscita; }
for( iAdp=0; iAdp<qAdp; ++iAdp ) {
for( iAbb=0; iAbb<qAbb; ++iAbb ) {
if( ad[iAdp].lMca == ab[iAbb].adpt.lMca ) {
if( !memcmp(ad[iAdp].mcAd,ab[iAbb].adpt.mcAd,ad[iAdp].lMca) ) {
_makepath( nfd, NULL, kStrCartellaAutoaperturaFile,
ab[iAbb].file, kStrEstFileDati );
err = kCodErrNoErr;
goto uscita;
}
}
}
}
err = kCodErrPCIgnoto;
}
uscita:
if( ad ) free( ad );
if( ab ) free( ab );
return err;
}
/*==============================================================================
salta un carattere dal file fSrc, assicurandosi che sia uguale a c
restituisce 1: tutto bene; restituisce 0: errore
==============================================================================*/
static int salta_char( FILE *fSrc, char c ) {
char cAux;
int letti = fscanf( fSrc, "%c", &cAux );
return (1==letti) && c==cAux;
}
/*==============================================================================
carica in s una stringa di lunghezza ls
leggendola carattere per carattere dal file fSrc
restituisce 1: tutto bene; restituisce 0: errore
==============================================================================*/
static int carica_stringa( FILE *fSrc, char *s, int ls ) {
if( fSrc && s && ls>=0 ) {
int i;
for( i=0; i<ls; ++i ) {
int letti;
char c;
letti = fscanf( fSrc, "%c", &c );
if( 1!=letti ) return 0;
s[i] = c;
}
s[i] = '\0';
return 1;
}
return 0;
}
/*==============================================================================
restituisce 1: tutto bene; restituisce 0: errore
==============================================================================*/
static int carica_uint( FILE *fSrc, UI *uint ) {
if( fSrc && uint ) {
UI uintAux;
int letti;
letti = fscanf( fSrc, "%u", &uintAux );
if( 1!=letti ) return 0;
*uint = uintAux;
return 1;
}
return 0;
}
/*==============================================================================
s: stringa contenente il Mac Address da convertire
ls: la lunghezza della stringa in s
mca: un buffer di lunghezza MAX_ADAPTER_ADDRESS_LENGTH
dove collocare il Mac Address convertito
restituisce 1: tutto bene; restituisce 0: errore
==============================================================================*/
static int converti_mac_address( const char *s, int ls, BYTE *mca ) {
if( s && mca && (ls>=0&&ls<=2*MAX_ADAPTER_ADDRESS_LENGTH) ) {
int i;
for( i=0; i<ls/2; ++i ) {
unsigned long aux;
char b2[4] = {'\0','\0','\0','\0'};
char *fine;
b2[0] = s[i+i];
b2[1] = s[i+i+1];
aux = strtoul( b2, &fine, 16 );
if( (fine==b2) || aux>255 ) return 0;
mca[i] = aux;
}
return 1;
}
return 0;
}
// verifica che il file fSrc si apra con i quattro caratteri identificativi
// "em@f" e carica l'intero senza segno che rappresenta la quantita' degli
// abbinamenti contenuti nel file
// qAbbinamenti: quantita' abbinamenti
// restituisce 1: tutto bene; restituisce 0: errore
static int leggi_intestazione_file( FILE *fSrc, UI *qAbbinamenti ) {
if( fSrc && qAbbinamenti ) {
char buff[256];
UI qaTmp;
if( !carica_stringa(fSrc,buff,4) ) return 0;
if( lstrcmp(buff,"em@f") ) return 0;
if( !salta_char(fSrc,'\t') ) return 0;
if( !carica_uint(fSrc,&qaTmp) ) return 0;
if( qaTmp>0 && !salta_char(fSrc,'\n') ) return 0;
// tutto bene
*qAbbinamenti = qaTmp;
return 1;
}
return 0; // errore
}
// alloca in memoria dinamica e popola un array di qAbbinamenti strutture di
// tipo Abbinamento_t, caricandone i dati dal file fSrc, restituendone il
// puntatore; tocca al chiamante liberare la memoria allocata
// qAbbinamenti: quantita' abbinamenti
// restituisce NULL: errore
static Abbinamento_t *carica_file_abbinamenti( FILE *fSrc, UI*qAbbinamenti ){
UI i, lEl, qaTmp; // qaTmp: quantita' abbinamenti temporaneo
Abbinamento_t *aa = NULL;
char buff[256];
if( !fSrc || !qAbbinamenti ) goto errore;
if( !leggi_intestazione_file(fSrc,&qaTmp) ) goto errore;
aa = calloc( qaTmp, sizeof(*aa) );
if( !aa ) return NULL;
for( i=0; i<qaTmp; ++i ) {
memset( buff, 0, sizeof(buff) ); // azzera il buffer
// carica il nome
if( !carica_uint(fSrc,&lEl) ) goto errore;
if( !salta_char(fSrc,'\t') ) goto errore;
if( !carica_stringa(fSrc,aa[i].adpt.nome,lEl) ) goto errore;
if( !salta_char(fSrc,'\t') ) goto errore;
// carica il Mac Address
if( !carica_uint(fSrc,&lEl) ) goto errore;
if( !salta_char(fSrc,'\t') ) goto errore;
if( !carica_stringa(fSrc,buff,lEl) ) goto errore;
if( !salta_char(fSrc,'\t') ) goto errore;
if( !converti_mac_address(buff,lEl,aa[i].adpt.mcAd) ) goto errore;
aa[i].adpt.lMca = lEl/2;
// carica la descrizione dell'adapter
if( !carica_uint(fSrc,&lEl) ) goto errore;
if( !salta_char(fSrc,'\t') ) goto errore;
if( !carica_stringa(fSrc,aa[i].adpt.desc,lEl) ) goto errore;
if( !salta_char(fSrc,'\t') ) goto errore;
// carica il nome del file abbinato
if( !carica_uint(fSrc,&lEl) ) goto errore;
if( !salta_char(fSrc,'\t') ) goto errore;
if( !carica_stringa(fSrc,aa[i].file,lEl) ) goto errore;
if( i!=qaTmp-1 && !salta_char(fSrc,'\n') ) goto errore;
}
*qAbbinamenti = qaTmp;
return aa;
errore:
free( aa );
return NULL;
}
static Adapter_t *rileva_adapter_correnti( UI*qAdapter ) {
DWORD e = ERROR_BUFFER_OVERFLOW, dwBufLen = 0;
UINT qAdd = 0, maxAdd = MAX_MCADDDFLT;
PIP_ADAPTER_INFO pAdapterInfo = NULL;
IP_ADAPTER_INFO *aAdapterInfo = NULL;
// i dati da restituire
Adapter_t *aAdapter = NULL;
if( !qAdapter ) goto errore;
while( e==ERROR_BUFFER_OVERFLOW ) {
// crea il buffer destinato a ricevere i dati da GetAdaptersInfo()
if( aAdapterInfo ) free( aAdapterInfo );
aAdapterInfo = calloc( maxAdd, sizeof(*aAdapterInfo) );
if( !aAdapterInfo ) goto errore;
dwBufLen = sizeof(*aAdapterInfo)*maxAdd; // [in] dimensioni del buffer
e = GetAdaptersInfo( aAdapterInfo, &dwBufLen );
if( ERROR_BUFFER_OVERFLOW == e ) { ++maxAdd; continue; }
if( e != ERROR_SUCCESS ) goto errore;
}
// alloca spazio per i dati da restituire
aAdapter = calloc( maxAdd, sizeof(*aAdapter) );
if( !aAdapter ) goto errore;
pAdapterInfo = aAdapterInfo; // puntatore all'adapter info corrente
for( qAdd=0; pAdapterInfo && qAdd<maxAdd; ++qAdd ) {
lstrcpy( aAdapter[qAdd].nome, pAdapterInfo->AdapterName );
lstrcpy( aAdapter[qAdd].desc, pAdapterInfo->Description );
aAdapter[qAdd].lMca = pAdapterInfo->AddressLength;
memcpy(aAdapter[qAdd].mcAd,pAdapterInfo->Address,aAdapter[qAdd].lMca);
pAdapterInfo = pAdapterInfo->Next; // prossimo Mac Address nella lista
}
free( aAdapterInfo ); aAdapterInfo = NULL;
*qAdapter = qAdd;
return aAdapter;
errore:
if( aAdapter ) free( aAdapter );
if( aAdapterInfo ) free( aAdapterInfo );
return NULL;
}
Ovviamente il programma comprende altri file, per cui alcuni elementi del codice sono dichiarati altrove.
Giusto per chiarire cosa "legge" la funzione carica_file_abbinamenti() riporto anche un esempio del possibile contenuto del file degli abbinamenti tra le descrizioni degli adapter e i nomi dei file contenenti i dati per il lancio dei programmi e l'apertura dei documenti.
em@f 26
38 {36903162-23A0-4699-8107-FC3828EE5B8A} 12 5AE3454A41C2 40 Microsoft Hosted Network Virtual Adapter 2 2B
38 {1650A3DE-C340-42E2-AB9B-F2AD4592E7C1} 12 1AE3454A41C2 38 Microsoft Wi-Fi Direct Virtual Adapter 2 2B
38 {C9EE5D2F-1D89-4AF8-9693-2B8D45219FD8} 12 28E3454A41C2 48 Qualcomm Atheros AR956x Wireless Network Adapter 2 2B
38 {C3F84BD2-BA9E-4F3A-853C-B685F5E07C9A} 12 201A05E00E01 34 Realtek PCIe GBE Family Controller 2 2B
38 {36903162-23A0-4699-8107-FC48283E5B8A} 12 5AE34544CFED 40 Microsoft Hosted Network Virtual Adapter 2 2D
38 {1650A3DE-C340-42E2-AB9B-F2AD5492E7C1} 12 1AE34544CFED 38 Microsoft Wi-Fi Direct Virtual Adapter 2 2D
38 {C9EE5D2F-1D89-4AF8-9693-2B8D45219FD8} 12 28E34544CFED 48 Qualcomm Atheros AR956x Wireless Network Adapter 2 2D
38 {C3F84BD2-BA9E-4F3A-853C-B685F9E35C9A} 12 201A05E00E33 34 Realtek PCIe GBE Family Controller 2 2D
38 {36903162-23A0-4699-8107-FC4824EE5B8A} 12 5AE34555D1B5 40 Microsoft Hosted Network Virtual Adapter 2 2I
38 {1650A3DE-C340-42E2-AB9B-F2AD5552E7C1} 12 1AE34555D1B5 38 Microsoft Wi-Fi Direct Virtual Adapter 2 2I
38 {C9EE5D2F-1D89-4AF8-9693-2B8D44519FD8} 12 28E34555D1B5 48 Qualcomm Atheros AR956x Wireless Network Adapter 2 2I
38 {C3F84BD2-BA9E-4F3A-853C-B685F9E05C9A} 12 201A05CA7F39 34 Realtek PCIe GBE Family Controller 2 2I
38 {5BF3BCF8-4B7C-447A-B8AE-BE70D5D3771F} 12 56DB35DB3536 40 Microsoft Hosted Network Virtual Adapter 2 3D
38 {6BA17D55-1732-4DE9-8380-849CDD95CAD2} 12 16DB35DB3536 38 Microsoft Wi-Fi Direct Virtual Adapter 2 3D
38 {9C85EE15-1E0D-42A3-8FA3-4AB570CA253F} 12 A4DB35DB3536 48 Qualcomm Atheros AR956x Wireless Network Adapter 2 3D
38 {975A0051-8BA0-424A-ABF2-CF0564CF5D9F} 12 F8A965066559 38 Broadcom NetLink (TM) Gigabit Ethernet 2 3D
38 {36903162-23A0-4699-8107-FC4828EE5B5A} 12 5AE345560FF1 40 Microsoft Hosted Network Virtual Adapter 2 3H
38 {1650A3DE-C340-42E2-AB9B-F2AD5595E7C1} 12 1AE345560FF1 38 Microsoft Wi-Fi Direct Virtual Adapter 2 3H
38 {C9EE5D2F-1D89-4AF8-9693-2B8D44519FD8} 12 28E345560FF1 48 Qualcomm Atheros AR956x Wireless Network Adapter 2 3H
38 {C3F84BD2-BA9E-4F3A-853C-B685F5E07C9A} 12 201A05E00965 34 Realtek PCIe GBE Family Controller 2 3H
38 {36903162-23A0-4699-8107-FC4828EE5B5A} 12 5AE3454A64C1 40 Microsoft Hosted Network Virtual Adapter 2 3I
38 {1650A3DE-C340-42E2-AB9B-F2AD5592E5C1} 12 1AE3454A64C1 38 Microsoft Wi-Fi Direct Virtual Adapter 2 3I
38 {C9EE5D2F-1D89-4AF8-9693-2B8D45219FD8} 12 28E3454A64C1 48 Qualcomm Atheros AR956x Wireless Network Adapter 2 3I
38 {C3F84BD2-BA9E-4F3A-853C-B685F5E07C9A} 12 201A05E8095F 34 Realtek PCIe GBE Family Controller 2 3I
38 {46A52897-0B8E-4D56-8F97-769601588A55} 12 1078D5C3F1C2 43 Intel(R) 82578DC Gigabit Network Connection 15 Aula insegnanti
38 {17D215E2-134B-4284-A9F1-4E32F3E5A847} 12 542AA5A9E52F 49 D-Link DWA-131 Wireless N Nano USB Adapter(rev.E) 15 Aula insegnanti
Ora, anche se il programma funziona, iniziano le fasi tediose della caccia ai difetti "occulti" e della previsione, individuazione e aggiramento delle situazioni "non ordinarie" (mancanza di file necessari, formattazioni errate dei dati, e così via).
Ancora grazie per l'aiuto che mi avete dato -- mancavo delle informazioni di base necessarie per scoprire da me le API delle quali avevo bisogno.