Come riconoscere in modo univoco una postazione PC?

di il
29 risposte

29 Risposte - Pagina 2

  • Re: Come riconoscere in modo univoco una postazione PC?

    AldoBaldo ha scritto:


    Non è che non voglio seguire i consigli, è che non si applicano alla situazione specifica nella quale mi trovo a voler cercare le soluzioni. Ad esempio, il codice che mi suggerisci usa un linguaggio col quale non ho alcuna dimestichezza, e fa almeno in apparenza riferimento ad ambienti di sviluppo diversi da quello che uso (Code::Blocks, con MinGw/gcc). Inoltre credo tiri in ballo delle classi, mentre io vorrei rimanere nell'ambito del comunissimo C. Ho inoltre necessità/desiderio di fare un programmino di dimensioni risibili e che possa "girare" su sistemi datati, arretrando almeno fino a XP, usando solo ed esclusivamente le API di base di Win32.

    E' possibile "tradurre" il tuo esempio affinché rientri in questa casistica?

    Spulciando la documentazione a mia disposizione, mi sono imbattuto in una funzione chiamata UUIDCreate(), che crea un fantomatico Unique Universal Identifier... potrebbe essere utile per ottenere gli scopi che ho descritto in precedenza?

    Se mi si indirizza verso una documentazione alla mia portata faccio anche da me. Probabilmente ho fatto le ricerche usando chiavi inadatte, perché non sono venuto a capo di niente.
    La domanda è: devi farlo all'interno di un tuo programma Windows-C?
    Perchè altrimenti c'è già getmac, bello che fatto.
    Così come ipconfig /all con find (lato batch).

    Quindi dall'inizio: parliamo di WIndows e programmelli C/C++?
    https://www.codeguru.com/code/legacy/network/GetMACAdapters.zip
  • Re: Come riconoscere in modo univoco una postazione PC?

    Parliamo di Windows e programmelli C, gli unici alla mia portata. Parliamo del desiderio di contenere le dimensioni del programma entro limiti ridottissimi, pochi KB (ma POCHI! diciamo una ventina al massimo?). Parliamo del fare una cosa che parta da stick USB alla velocità del pensiero, faccia UNA cosa e si chiuda alla velocità della luce, senza complicazioni -- click (o autorun), capisce su che computer sta girando, lancia una manciata di programmi e apre con essi una manciata di documenti in relazione al computer riconosciuto, quindi si chiude e buonanotte. La parte "operativa" l'ho già bell'e pronta, mi manca la parte di riconoscimento della postazione.
  • Re: Come riconoscere in modo univoco una postazione PC?

    AldoBaldo ha scritto:


    Parliamo di Windows e programmelli C, gli unici alla mia portata. Parliamo del desiderio di contenere le dimensioni del programma entro limiti ridottissimi, pochi KB (ma POCHI! diciamo una ventina al massimo?).
    Ti ho messo il sorgente di un programma sui 30KB.
  • Re: Come riconoscere in modo univoco una postazione PC?

    Sì, l'ho visto dopo averti già risposto. Lo stavo "spulciando".
    Ho cercato sul web la funzione che utilizza. Ovviamente la ricerca mi ha rimandato alla documentazione online di Microsoft. Il problema era che la MIA documentazione è troppo "antica" e non prevede GetAdaptersInfo() (da quel che ho letto pare risalire a Windows 2000, e io uso il "Win32 help" del '98).

    Dunque, copia, incolla, compila come C... tutto bene! Leggo i commenti nel codice e consulto un po' di documentazione online... sì, niente di sconvolgente (meno male!). "Spio" l'esecuzione nel debugger... ok, fa il suo dovere (non avevo dubbi che sapeste la soluzione; non ero sicuro che me la avreste voluta fornire). Però... però... ho qualche domanda alla quale non trovo risposta da solo.

    1) dichiara un array AdapterInfo[16] -- perché proprio 16? è una quantità arbitraria o ci sono delle specifiche da rispettare?
    2) come mai è stato usato un array AdapterInfo[16] se IP_ADAPTER_INFO pare predisposto alla gestione di una lista collegata (come vedo anche nel debugger, con il campo "next" che è sempre uguale all'indirizzo dell'elemento successivo, con il "next" dell'ultimo elemento che punta a NULL)? Ci sono ragioni che mi sfuggono? Mi aspettavo un uso dell'array tramite indici.
    3) GetAdaptersInfo() può restituire più elementi IP_ADAPTER_INFO, come faccio a capire qual è quello che mi interessa? La loro posizione è fissa nell'ordine della lista restituita? (nel qual caso potrei prendere in considerazione sempre il primo, per dire, e ignorare gli altri).

    EDIT: il programma che mi hai passato, compilato in C (non C++) con il compilatore che uso è di 8704 bytes soltanto, non 30KB! Meglio ancora!
  • Re: Come riconoscere in modo univoco una postazione PC?

    1-2 non lo so, francamente sono troppo pigro per controllare questa merda m$
    3) puoi avere più schede di rete su ogni PC. Devi nel caso prendere le informazioni aggiuntive (tipo il nome della scheda di rete).
    Nessuno vieta di avere due, tre o 10 schede ethernet. Che te ne fotte? Piglia il primo, il secondo, o l'ultimo e vivi felice.
    Ti turberebbe solo il caso in cui si cambi l'hardware della macchina (o si inseriscano schede di rete virtuali, ad es. virtualbox, vmware etc)
  • Re: Come riconoscere in modo univoco una postazione PC?

    Tu ti senti "pigro", io mi sento "curioso". Penso che la differenza stia nel fatto che per me è un passatempo, per te un mestiere. Comprendo e non chiedo oltre, però procedo nelle letture, magari scopro qualcosa (non che mi serva davvero, solo per poter dire: "toh, the roba!").

    Seguendo il tuo consiglio, dunque, provo a usare sempre il primo elemento restituito e a vedere cosa succede. Casomai qualcuno cambiasse la configurazione degli apparecchi mi basterebbe aggiornare il file di riferimento per abbinare i codici alle aule e nulla più, dunque non sarebbe quel gran dramma. Comunque, sai che voglia che hanno i colleghi che sono COSTRETTI a gestire queste cose [gratis] di mettersi a smanettare per cambiare configurazioni! Salvo guasti, non cambieranno MAI, ed è giusto e bene che sia così.

    Dita incrociate. Tornerò a dire come è andata.
    Grazie per l'aiuto e per gli spunti (ora so qualcosa che prima non sapevo, e conserverò la documentazione che mi hai aiutato a scoprire).
  • Re: Come riconoscere in modo univoco una postazione PC?

    La funzione riceve un buffer della necessaria dimensione per impostare la lista collegata. In questo caso viene fornito un buffer utile a memorizzare i dati di 16 schede di rete (in genere bastano), ma è possibile passarne anche di più. Una volta passato il buffer, se sufficiente, questo viene riempito.
    La funzione tuttavia non è una scelta ottimale perché non restituisce il "Friendly Name" dell'interfaccia che è quella mostrata da Windows.

    L'ordine dell'elenco non è prevedibile, non ti affidare a come viene restituita la lista, anche nello stesso PC.

    O ti basi sul Friendly Name o sulla Description o Adapter Name.

    Per quanto riguarda gli indirizzi ottenuti, se sono più di uno, fai una lista per PC e cercane almeno uno.

    Ti suggerisco questo codice, che usa un'altra funzione suggerita da MS al posto di quella del codice precedente, adattato da me per semplificare un esempio MS, su cui, sono sicuro, ragionerai un po'
    
    #include "stdafx.h"
    
    #include <winsock2.h>
    #include <iphlpapi.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #pragma comment(lib, "IPHLPAPI.lib")
    
    
    #define WORKING_BUFFER_SIZE 15000
    #define MAX_TRIES 3
    
    
    #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
    #define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
    
    
    int main(int argc, char **argv)
    {
    	DWORD dwRetVal = 0;
    
    	unsigned int i = 0;
    
    	ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
    	LPVOID lpMsgBuf = NULL;
    
    	PIP_ADAPTER_ADDRESSES pAddresses = NULL;
    	ULONG outBufLen = 0;
    	ULONG Iterations = 0;
    
    	PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
    
    	outBufLen = WORKING_BUFFER_SIZE;
    
    	do {
    		pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen);
    		if (pAddresses == NULL) {
    			printf
    			("Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n");
    			exit(1);
    		}
    
    		dwRetVal = GetAdaptersAddresses(AF_INET, flags, NULL, pAddresses, &outBufLen);
    
    		if (dwRetVal == ERROR_BUFFER_OVERFLOW)
    		{
    			FREE(pAddresses);
    			pAddresses = NULL;
    		}
    		else 
    		{
    			break;
    		}
    
    		Iterations++;
    	} while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));
    
    	if (dwRetVal == NO_ERROR)
    	{
    		pCurrAddresses = pAddresses;
    
    		while (pCurrAddresses) 
    		{
    			if (pCurrAddresses->IfType == IF_TYPE_ETHERNET_CSMACD) 
    			{
    				printf("\tAdapter name: %s\n", pCurrAddresses->AdapterName);
    				printf("\tDescription: %wS\n", pCurrAddresses->Description);
    				printf("\tFriendly name: %wS\n", pCurrAddresses->FriendlyName);
    
    				if (pCurrAddresses->PhysicalAddressLength != 0) {
    					printf("\tPhysical address: ");
    					for (i = 0; i < (int)pCurrAddresses->PhysicalAddressLength;
    						i++) {
    						if (i == (pCurrAddresses->PhysicalAddressLength - 1))
    							printf("%.2X\n",
    							(int)pCurrAddresses->PhysicalAddress[i]);
    						else
    							printf("%.2X-",
    							(int)pCurrAddresses->PhysicalAddress[i]);
    					}
    				}
    			}
    
    			printf("\n");
    
    			pCurrAddresses = pCurrAddresses->Next;
    		}
    	}
    	else 
    	{
    		printf("Call to GetAdaptersAddresses failed with error: %d\n", dwRetVal);
    		if (dwRetVal == ERROR_NO_DATA)
    			printf("\tNo addresses were found for the requested parameters\n");
    		else
    		{
    			if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
    				FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
    				NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    				// Default language
    				(LPTSTR)&lpMsgBuf, 0, NULL)) {
    				printf("\tError: %s", lpMsgBuf);
    				LocalFree(lpMsgBuf);
    				if (pAddresses)
    					FREE(pAddresses);
    				exit(1);
    			}
    		}
    	}
    
    	if (pAddresses) 
    	{
    		FREE(pAddresses);
    	}
    
    	return 0;
    }
    
  • Re: Come riconoscere in modo univoco una postazione PC?

    GetAdaptersAddresses() l'avevo già notata quando ho cercato GetAdaptersInfo(), ed ho visto che pare molto più completa. Il codice dell'esempio che mi hai proposto l'ho scorso riga per riga e ho capito cosa fa. Fin qui tutto bene.

    Trovo anche utile la tua precisazione secondo la quale non c'è garanzia che un certo dato stia sempre nella stessa posizione della lista restituita (se non ho capito male, +m2+ sosteneva il contrario... sapendone NULLA per parte mia, a questo punto sono un po' confuso -- se non altro ora so che non devo dare niente per scontato).

    Non ho capito invece il riferimento a Friendly name, Adapter name e Description... si tratta di stringhe, a quel che vedo, quindi con ogni probabilità destinate a lettura da parte di un occhio umano. Ogni postazione ha stringhe uniche? Mi sembra strano, perché le immagino un po' come indicatori di una marca, o di un modello di automobili: posso avere 2000 Panda, e si chiamano tutte Panda, distinguibili non in quanto Panda, bensì in quanto dotate di targhe diverse. Dunque, cercando un nome, non rischio di avere dei doppioni? O forse intendi dire che mi conviene prendere (per dire) il Friendly name come primo oggetto di ricerca, poi (una volta trovato quello che combacia) verificare il codice numerico che corrisponde allo stesso Friendly name su un'altra postazione?

    Lo so che potrei fare da me le dovute ricerche, ma capirai che dovendole fare in servizio, su postazioni collocate in stanze diverse e andando a caccia dei "buchi" orari in cui quelle stanze non sono utilizzate, la cosa diventa un po' macchinosa. Non da un punto di vista di programmazione, proprio da un punto di vista logistico MOLTO fisico. Stando terra-terra, puoi darmi qualche delucidazione in più? A questo punto, direi che di esempi di codice ne ho a sufficienza, basandomi su quel che mi avete suggerito posso ragionare e trovare le soluzioni anche da me (anche perché ho scoperto le pagine della documentazione "ufficiale" delle API), però non ho abbastanza basi su quel che sta DIETRO alla terminologia -- quali di quegli elementi sono univoci e quali no? Per identificare una postazione devo considerare contemporaneamente più elementi anziché uno solo?
  • Re: Come riconoscere in modo univoco una postazione PC?

    Basta leggere la documentazione.

    Per la GetAdaptersInfo :
    "In versions prior to Windows 10, the order in which adapters appear in the list returned by this function can be controlled from the Network Connections folder: select the Advanced Settings menu item from the Advanced menu. Starting with Windows 10, the order is unspecified."

    Quindi, prima di Windows 10, l'ordine è determinato dall'impostazione avanzata nel folder delle connessioni (che può essere modificato e quindi imprevedibile), da Windows 10 è proprio non specificato.

    Per la GetAdaptersAddresses :
    "In versions prior to Windows 10, the order in which adapters appear in the list returned by this function can be controlled from the Network Connections folder: select the Advanced Settings menu item from the Advanced menu. Starting with Windows 10, the order in which adapters appear in the list is determined by the IPv4 or IPv6 route metric."

    Per questa funzione, vale lo stesso della precedente prima di Windows 10, mentre da Windows 10 l'ordine è per v4/v6 ma non sempre non specificato.
    Non ho capito invece il riferimento a Friendly name, Adapter name e Description... si tratta di stringhe, a quel che vedo, quindi con ogni probabilità destinate a lettura da parte di un occhio umano. Ogni postazione ha stringhe uniche?
    Attento .... quelle stringhe NON ti servono ad identificare univocamente il PC. Ti servono ad individuare, nel caso di presenza di molte schede di rete, quella che ti serve esaminare, solo se esiste uno standard nelle aule e le schede sono denominate allo stesso modo nel folder delle connessioni (ad esempio, "Rete Aula").

    In alternativa (che poi è la soluzione consigliata), puoi leggere tutti i MAC di tutte le schede e cercarne almeno uno che ti identifica la macchina.
  • Re: Come riconoscere in modo univoco una postazione PC?

    Porta pazienza se faccio il noioso, ma è per evitare di dover fare e rifare le stesse cose cento volte (delle quali cento e una sbagliate). Faccio un'ipotesi di procedimento.

    Prima fase: preparo un programmino ausiliario (non mi ci vuole poi molto, se serve) che mi dia un elenco delle schede presenti su una certa postazione, e lo usa per verificare che tipi di schede ci sono nelle aule; se ne identifico un tipo ricorrente decido di usare quello come riferimento.

    Seconda fase: rifaccio il giro delle aule con lo stesso programmino e predispongo un file nel quale colloco l'elenco dei codici di quelle schede, e solo di quelle, abbinandone ciascuno al nome/numero dell'aula dove si trova la postazione, creando una "tabella formattata" di un qualche tipo

    Terza fase: predispongo il programma di lancio automatico in modo che all'avvio legga tutte le schede presenti sulla postazione dove avviene il lancio, facendone un elenco, quindi legga la tabella dal file predisposto nella seconda fase dallo stick USB, quindi (confrontando i due elenchi voce per voce) trovi la corrispondenza tra il codice sul file e il codice trovato sulla postazione per il tipo di scheda che ho deciso di usare come riferimento e mi dia in uscita nella forma che mi serve il riferimento all'aula dove ci si trova

    Può funzionare, secondo te? Una cosa di questo tipo penso (spero) di essere in grado di farla.
  • Re: Come riconoscere in modo univoco una postazione PC?

    A grandi linee sì. Vedi un po' il risultato della collezione dei dati prima di passare alla terza fase (in modo da avere le idee chiare prima di scrivere il programma).
  • Re: Come riconoscere in modo univoco una postazione PC?

    Bene! Grazie, allora. Mi ci metto, anche se credo che ci vorrà un po' (per via della impossibilità di fare le prove e le verifiche "sul campo" in quattro e quattr'otto), poi scriverò di nuovo qui per dire com'è andata (magari se qualcuno ha seguito la discussione può trovarne interessante l'epilogo).
  • Re: Come riconoscere in modo univoco una postazione PC?

    Scusa ma...
    1) elenca i mac per ogni macchina
    2) scegline uno per macchina quello che vuo

    3) per riconoscere fai elencare i mac (come 2). Appena trovi il Mac scelto hai finito

    Non ti serve confrontare voce per voce, non è deterministico l'elenco.
    Ma che ti frega? Ne basta uno solo.

    Mi sembra facile, non ti complicare la vita.
    per 1 su Windows c'è getmac addirittura
  • Re: Come riconoscere in modo univoco una postazione PC?

    Passando alla fase "concreta" tengo conto di tutto quel che mi avete detto. TUTTO. Del maiale non si butta via niente (conosci il detto?) Prenderò la decisione finale solo dopo aver visto come vanno le cose con i vari metodi verso i quali mi avete indirizzato. Spero di non perdermi per strada (se fosse chiederei ancora).
  • Re: Come riconoscere in modo univoco una postazione PC?

    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.
Devi accedere o registrarti per scrivere nel forum
29 risposte