Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 17
  1. #1
    Utente di HTML.it
    Registrato dal
    Nov 2013
    Messaggi
    98

    [C] Confronto percorsi in BYTE

    Come effettuo un controllo tra due percorsi espressi in BYTE?
    Ho provato con l'if ma non funzia

  2. #2
    Perché ti ostini ad usare percorsi in "BYTE"? Non ha nessun senso, se è una stringa o usi CHAR/char o WCHAR/wchar_t o TCHAR. Di nuovo: un array di BYTE non è un tipo sensato per una stringa (che poi ce la si possa fare stare è un altro discorso).

    Come già detto di là, se vuoi ottenere un aiuto sensato devi specificare tutto il contesto (e ti ricordo nuovamente che il linguaggio di riferimento va specificato nel titolo).
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,466
    Ma non avevi risolto? Non hai neanche risposto nell'altro thread ...
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  4. #4
    Utente di HTML.it
    Registrato dal
    Nov 2013
    Messaggi
    98
    Quote Originariamente inviata da MItaly Visualizza il messaggio
    Perché ti ostini ad usare percorsi in "BYTE"? Non ha nessun senso, se è una stringa o usi CHAR/char o WCHAR/wchar_t o TCHAR. Di nuovo: un array di BYTE non è un tipo sensato per una stringa (che poi ce la si possa fare stare è un altro discorso).

    Come già detto di là, se vuoi ottenere un aiuto sensato devi specificare tutto il contesto (e ti ricordo nuovamente che il linguaggio di riferimento va specificato nel titolo).
    Sto sviluppando una funzione di AutoRun. Ho preso un codice di autorun sul Web ed una funzione in particolare, richiede che il percorso sia in BYTE.

    codice:
    GetModuleFileName(NULL, (LPSTR)ProgramPath, MAX_PATH);
    
    HKEY hKey;
    LONG err;
    TCHAR RegValue[] = " ";
    err=RegCreateKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&hKey);
    
    
    if(err!= ERROR_SUCCESS) cout << "Error create key";
              err=RegSetValueEx(hKey,RegValue,0,REG_SZ,ProgramPath,MAX_PATH);

    Una volta che il programma viene avviato in automatico tramite un'altra funzione controllo se il percorso rilevato nella prima funzione corrisponde al reale percorso dell'eseguibile (quest'ultimo potrebbe essere infatti stato spostato in un'altra cartella e ciò non avvierebbe il programma in automatico al successivo avvio).

    Ho quindi la necessità di effettuare un controllo tra il percorso rilevato all'avvio e quello attuale. Spero di essermi spiegato.

    Quote Originariamente inviata da oregon Visualizza il messaggio
    Ma non avevi risolto? Non hai neanche risposto nell'altro thread ...
    Hai detto che per un nuovo problema bisogna aprire un altro Thread. Per risolto intendevo il problema principale dell'altro Thread.

  5. #5
    Il BYTE * della RegSetValueEx è solo un placeholder per un generico puntatore a roba da memorizzare nel registro; la cosa giusta è usare i TCHAR ovunque e compilare con Unicode abilitato (visto che non ha più senso da più di un decennio compilare ANSI sotto Windows) o, forse anche meglio, usare direttamente le versioni Unicode delle API (RegCreateKeyW, RegSetValueExW) e usare caratteri WCHAR. In un caso per fare il confronto devi usare _tcscmp, nell'altro wcscmp.
    Ultima modifica di MItaly; 23-04-2014 a 21:20
    Amaro C++, il gusto pieno dell'undefined behavior.

  6. #6
    Utente di HTML.it
    Registrato dal
    Nov 2013
    Messaggi
    98
    Quote Originariamente inviata da MItaly Visualizza il messaggio
    Il BYTE * della RegSetValueEx è solo un placeholder per un generico puntatore a roba da memorizzare nel registro; la cosa giusta è usare i TCHAR ovunque e compilare con Unicode abilitato (visto che non ha più senso da più di un decennio compilare ANSI sotto Windows) o, forse anche meglio, usare direttamente le versioni Unicode delle API (RegCreateKeyW, RegSetValueExW) e usare caratteri WCHAR. In un caso per fare il confronto devi usare _tcscmp, nell'altro wcscmp.
    Ma tra WCHAR, TCHAR e CHAR cosa cambia?

  7. #7
    Di base CHAR è un typedef per char, WCHAR è un typedef per wchar_t.
    In ambito Windows, quando si parla di stringhe "ANSI", "multibyte" o "narrow" si parla di stringhe costituite da CHAR (ovvero, da caratteri ad 8 bit). L'encoding delle stringhe ANSI dipende dal codepage corrente, che di default dipende dalla lingua di sistema. In base all'encoding cambiano o semplicemente i caratteri oltre al 127 (ad esempio, per il CP usato in Italia ci saranno le lettere accentate, per quello russo le lettere cirilliche), oppure per le lingue dell'est ci sono diversi encoding multibyte abbastanza complessi (tipo Shift-JIS). Comunque, il punto fondamentale è che su Windows le stringhe narrow sono encodate con un encoding locale e che non può rappresentare qualunque carattere, ma solo un subset relativo alle impostazioni internazionali correnti.

    Inizialmente Windows lavorava solo con stringhe narrow internamente (tutto il filone Windows 9x è andato avanti così), ma questo presenta seri problemi se si vuole lavorare sullo stesso computer con qualunque carattere, indipendentemente dalle impostazioni internazionali; per questo motivo da Windows NT in poi (e quindi anche XP, Vista & co.) il sistema operativo nativamente usa Unicode, uno standard che consente di rappresentare qualsiasi carattere.

    Fino a circa il 1995 i caratteri codificabili in Unicode erano meno di 65536, per cui Windows NT (e altri software iniziati a scrivere in quel periodo) ha fatto la scelta di usare per tutte le API Unicode (oltre che al suo interno) l'encoding UCS-2, per cui, invece di usare char da 8 bit, si usano wchar_t (WCHAR nel "linguaggio" di Windows) da 16 bit. In questa maniera, ogni stringa Unicode è un array di WCHAR, ciascuno dei quali può rappresentare un qualunque carattere Unicode. (incidentalmente, la questione è deragliata dopo il 1995 per il fatto che l'Unicode è stato espanso, per cui dei WCHAR da 16 bit non bastavano più; da UCS-2 si è passati ad UTF-16 - ovvero, sempre WCHAR, ma con encoding a larghezza variabile - perdendo l'unico vantaggio dell'UCS-2 rispetto all'UTF-8, con il risultato che Windows ha sconvolto la sua ABI per finire col lavorare internamente con il peggiore encoding di stringhe possibile )

    Ora, per compatibilità con Windows 95 & co. tutte le API di Windows (o quasi) esistono in due versioni differenti: una versione "Unicode", che è quella nativa del sistema operativo, che opera con i WCHAR; e una versione "ANSI", che accetta stringhe ANSI (interpretate secondo il codepage corrente), le converte al volo in Unicode (WCHAR) e chiama la versione Unicode della API.
    In questa maniera, programmi scritti con "in mente" i CHAR e i codepage locali potevano continuare a funzionare (rimanendo soggetti alle limitazioni dell'uso del codepage corrente), e i nuovi programmi potevano invece lavorare in Unicode.

    Se però torniamo al periodo 1995-2000 si poneva un problema: i sistemi NT supportavano Unicode, ma i sistemi di famiglia Windows 9x no (o meglio, in maniera molto limitata), per cui un programma scritto per usare le APi Unicode non sarebbe potuto girare su Windows 9x, e uno scritto con le API ANSI avrebbe conservato le limitazioni dei codepage anche su Windows NT.

    Per aggirare questo problema, Microsoft si è inventata l'accrochione dei TCHAR.
    Un TCHAR è un typedef che dipende dall'impostazione di Unicode del progetto che compili (ovvero dal fatto che sia definita o meno la macro _UNICODE o UNICODE, ora non ricordo esattamente); se la macro UNICODE è definita, allora i TCHAR sono WCHAR, altrimenti sono CHAR.
    Non solo: tutte le API (e numerose struct usate con le API) in realtà sono #define o typedef fatti a questa stessa maniera: la API (ad esempio) GetModuleFileName non esiste come funzione esportata dalle dll di Windows: esistono la GetModuleFileNameW (la versione "vera" Unicode) e la GetModuleFileNameA (la versione ANSI). Tuttavia, al momento della compilazione negli header di Windows c'è una cosa del tipo:
    codice:
    #ifdef _UNICODE
        #define GetModuleFileName GetModuleFileNameW
    #else
        #define GetModuleFileName GetModuleFileNameA
    #endif
    Anche la libreria standard contiene numerose "funzioni" (di fatto #define) per lavorare sui TCHAR (ad esempio, _tcslen diventa wcslen se _UNICODE è definito o strlen in caso contrario). Altra cosa fondamentale, viene fornita la macro _T (alias per la macro TEXT) per racchiudere le stringhe literal, in modo che siano specificate come stringhe ANSI o wide a seconda dell'impostazione di Unicode.

    In questa maniera, era (ed è tuttora) possibile da un unico set di sorgenti compilare un'applicazione "in ANSI" (ovvero, che internamente lavora con char e API ANSI) e "in Unicode" (ovvero, che usa i WCHAR e le API Unicode). Ai tempi in effetti non era raro fornire due eseguibili, uno ANSI per Windows 9x e uno Unicode per Windows NT.

    Fast forward ad oggi, su Windows non ha più nessun senso compilare in ANSI, dato che tutte le versioni di Windows attualmente in uso supportano Unicode, e non usarlo può dare problemi in caso di input di caratteri/simboli "strani", e soprattutto con i percorsi di file - se la tua applicazione lavora con il codepage locale potrebbe non poter nemmeno rappresentare certi percorsi contenenti caratteri "strani".

    Per questo, oggi ci sono diverse scuole di pensiero:
    • continuare ad usare i TCHAR e le "finte API" (ovvero, le macro senza "A" o "W" in fondo), ma compilare sempre e comunque con Unicode abilitato;
    • lasciare perdere l'anacronismo dei TCHAR, e usare direttamente i WCHAR; a seconda dei gusti, si potrebbero usare o le "finte API" (ovviamente compilando con Unicode abilitato) o richiamare esplicitamente le API Unicode (con la W in fondo);
    • (c'è anche la scuola di pensiero di quelli che dicono di usare internamente al programma stringhe narrow codificate in UTF-8 (un encoding che consente di memorizzare qualunque carattere Unicode in stringhe di char a 8 bit "normali") e di convertirle in UTF-16 solo al momento di chiamare le API, ma la cosa non è semplicissima dato che Windows non ha un gran supporto per UTF-8)


    Tornando a noi, quello che farei io nel tuo caso sarebbe abilitare il flag Unicode nel progetto e usare dovunque stringhe e API wide, in modo da evitare sorprese di encoding.
    Ultima modifica di MItaly; 24-04-2014 a 01:41
    Amaro C++, il gusto pieno dell'undefined behavior.

  8. #8
    Utente di HTML.it
    Registrato dal
    Nov 2013
    Messaggi
    98
    Da quanto ho potuto capire la compilazione in DEV C++ avviene direttamente in Unicode, è possibile?

    Ho trasformato la funzione GetModuleFileName in GetModuleFileNameW come da te consigliatomi. Ora però riscontro dei problemi con la funzione RegSetValueExW

    codice:
    WCHAR RegValue[] = "ossecurity";
    Errore: int-array initialized from non-wide string


    codice:
    err=RegSetValueExW(hKey,RegValue,0,REG_SZ,ProgramPath,MAX_PATH);
    Errore: cannot convert `WCHAR*' to `const BYTE*' for argument `5' to `LONG RegSetValueExW(HKEY__*, const WCHAR*, DWORD, DWORD, const BYTE*, DWORD)'
    Ultima modifica di Tiime; 24-04-2014 a 17:41

  9. #9
    1. Le stringhe literal wide nel codice vanno specificate premettendo una L alle virgolette. Per cui, sarà:
    codice:
    WCHAR RegValue[] = L"ossecurity";
    2. Nonostante sia la versione Unicode di RegSetValueEx, il quinto parametro resta un BYTE* (dato che la RegSetValueEx viene usata per memorizzare dati di ogni tipo, non solo stringhe). Per questo motivo, devi fare un cast del buffer a BYTE*.
    3. Le dimensioni da specificare nell'ultimo parametro non sono quelle dell'intero buffer (che non è detto sia pieno), ma solo quelle dei dati validi, compreso il terminatore NUL, specificate in byte. Per questo motivo, passaci (wcslen(ProgramPath) +1)*sizeof(WCHAR).
    Amaro C++, il gusto pieno dell'undefined behavior.

  10. #10
    Utente di HTML.it
    Registrato dal
    Nov 2013
    Messaggi
    98
    Quote Originariamente inviata da MItaly Visualizza il messaggio
    Le dimensioni da specificare nell'ultimo parametro non sono quelle dell'intero buffer (che non è detto sia pieno), ma solo quelle dei dati validi, compreso il terminatore NUL, specificate in byte. Per questo motivo, passaci (wcslen(ProgramPath) +1)*sizeof(WCHAR).
    Perché si moltiplica la lunghezza del ProgramPath per la lunghezza del WCHAR? La sola lunghezza del ProgramPath, che è un vettore di MaxPath, +1 non dovrebbe già dare la massima lunghezza disponibile?

    PS: per usare la funzione WSTRCMP che libreria serve?

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.