Newsgroup: it.comp.lang.c++
Titolo: Serial number di un HD

        Ciao a tutti
Sto diventando matto cercando di leggere il serial number di un disco rigido.
Una volta (oh paradiso felice) usavo il Borland C++ v1.0 (la versione
dev'essere dell'87 o giù di lì) e non avevo problemi (o quasi) a generare un
interrupt con i dati giusti nei registri... adesso con 'sti nuovi mostri di
"Visual tutto ed anche di più" sembra che il buon vecchio hardware non esista
più.  :-(
Scherzi a parte i parametri del mio problema sono i seguenti:
0) l'ambiente è Dos/Win95/Win98 (non Dos puro (sigh) e nemmeno Win/NT o Unix),
il compilatore è l'MS VC++ 4.0. In teoria (e, spero, anche in pratica) potrei
dover costruire quella che il VC chiama una Consolle application (cioè un prg
.EXE che gira in Dos senza bisogno di Win). Ma siccome sono sicuro che la
routine mi serve sia in Dos che in Win l'informazione che chiedo è per tutte e
due, tenendo conto del fatto che quella che girerà in Dos lo farà prima della
partenza di Windows.
1) come programmatore non valgo una cicca: conosco un pò il C e quasi nulla
del C++ (la cui sintassi già mi spaventa). Sarei però più che disposto ad
impararlo se trovassi qualcuno paziente da stressare ogni tanto per un hint qui
e là.
2) da alcuni giorni (ebbene sì) giro sconsolato per l'help-on-line del VC++
4.0 e dopo parecchio cercare ho trovato UN esempio (della Microsoft) il quale
però risulta indigesto al compilatore (sempre Microsoft) a causa di un sacco di
cose per le quali non si trovano le definizioni (dalla chiamata _far *p
all'utilizzo di REGS e SREGS per la gestione degli interrupt).
3) disperato come pochi (lo giuro) sono andato a scaricare (infognandomi) la
gigantesca Interrupt List di Ralf Brown (3 MB di liste ed utilities che
diventano, dopo non poco lavoro, 5 MB di file .HLP) sperando di trovare qualche
informazione su un mitico interrupt per leggere 'sto serial number del cavolo.
La lista l'ho scaricata ed ho trovato i parametri da settare nei registri... ma
VC (non sarebbe più corretto chiamarlo W.C. ?) si rifiuta di lavorare con REGS
e SREGS se prima non gli dichiaro qualche .H che credo di non avere.
 Stavo per impelagarmi in modo micidiale andando ad installare SoftICE e
tracciando l'esecuzione del comando DIR (ebbene sì !!! anche la stupidissima
Dir riesce a leggere il Serial#) quando mi sono detto: "perché prima di
suicidarmi non chiedo aiuto agli amici di un newsgroup su C/C++ ?"... ed eccomi
qui ad implorare.  :-)
        Bye
        Sky
/* togliere il '-' davanti all'e_mail
    per rispondermi direttamente
    oppure 
men...@writeme.com
 */
P.S.
Queste info mi servono per costruire una utility che potrebbe aiutare me e
(spero) parecchia altra gente. Dato che, vista la mia altissima scienza
programmatoria, non ne ho mai fatto un problema di soldi, il software
sviluppato sarà sicuramente (F)reeware.

e SREGS se prima non gli dichiaro qualche .H che credo di non avere.
Che io sappia, Visual C++ (che non c'e` nessuna particolare ragione
di fare bersaglio di infantili insulti) non usa REGS, SREGS, o nulla del
genere; se, per qualsivoglia ragione, ti occorre un accesso a livello
assembler, lo ottieni con la keyword __asm -- ad esempio, per caricare
nel registro EAX il valore della variabile C o C++ pippo,
    __asm mov eax, pippo
(se devi usare un blocco sostanzioso di codice assembler in linea, puoi
farlo usando __asm una sola volta e le parentesi graffe attorno al blocco).
Non so con la vecchia versione che hai tu, ma gia` con la 5.0 questo era
documentato piuttosto bene nella documentazione in linea del VC++.
Alex

Ci vuole la parola magica : "GetVolumeInformation(..)"
Ciao,
Amos

Ci vuole la parola magica : "GetVolumeInformation(..)"
 Eh già... ci vuole la parola magica... ci vuole la parola magica... ma se
l'avessi saputa che ci venivo a fare, meschino meschinello, tra voi genii del
C++ ?  :-)
 Scherzi a parte: se in C++ (ed insisto sul ++) fossi solo una zappa mi
riterrei già fortunato.  :-(


documentato piuttosto bene nella documentazione in linea del VC++.
Anche con VC++ 4.0 funziona così ma, come ripeto, (per fortuna) al momento non
ne ho bisogno.  :-)
Ti ringrazio veramente tanto per la prontezza e completezza dell'aiuto... e
ovviamente mi riservo di venirti a rompere le pa££e in futuro quando
m'incaglierò su altre (per te) inezie.
Ovviamente se qualcuno è interessato all'argomento e/o ha i miei stessi
problemi (cambio frequente della configurazione degli HDs) sappia fin d'ora che
tutto quanto produrrò sull'argomento sarà (F)reeware (che detto da me suona un
pò come una minaccia). ;-)))))


che vuol dire LPDWORD, TCSTR, ecc.).
Prego!  Queste parolacce maiuscole sono tutte delle macro (cioe`
dei #define del preprocessore) -- perche` Microsoft non abbia invece
scelto di usare typedef, mah, certo ragioni perse nei meandri della
storia.  Trovi un riassunto dei principali tipi (e parecchi di nessuna
importanza:-) sotto Platform SDK|Reference|Simple Types (nella
doc in linea del VC++5, ma anche in tanti altri modi, tipo l'MSDN in
linea, il Platform SDK che puoi scaricare, ecc ecc).  Molte che
vedrai hanno ragioni d'esistere solo storiche, ad esempio LPARAM
e WPARAM oggi sono entrambi di 32 bit -- sono distinti solo perche`
un tempo, sotto Win 1.0 e successive versioni a 16 bit, LPARAM
era di 32 bit ma WPARAM solo di 16 (L per Long, W per Word).
Forse l'unica cosa non di comprensione immediata nella lista sono
i tipi con T (che sta, credo, per "text"), come TCHAR, definito "un
carattere Unicode o Windows", LPCTSTR, "puntatore a una
stringa costante terminata da zero di caratteri Unicode o Windows",
ecc ecc.  La distinzione "Unicode o Windows" devi farla al momento
della compilazione, settando o meno le macro di preprocessore
UNICODE e _UNICODE (la seconda con un underline davanti; la
distinzione fra le due e` nebulosa -- settale sempre entrambe, o
nessuna delle due, per evitare problemi!-).  In Windows/NT, e credo
anche in Windows/CE, il sistema internamente funziona in Unicode
(caratteri di 16 bit), per potere girare allo stesso modo in tutto il
mondo (compreso Giappone ecc ecc); quindi, e` molto piu`
efficiente se anche il tuo programma fa tutto in Unicode.  Visual
Basic, e Java su tutte le piattaforme, funzionano infatti solo cosi`,
con Unicode come rappresentazione interna di ogni stringa.  In
C e C++, invece, hai tu, programmatore, la scelta.  Il problema e`
che Windows/95 NON supporta Unicode (Windows/98, mi pare,
supporta Unicode "esternamente", anche se internamente usa
ancora caratteri a 8 bit -- quindi, l'efficienza va nell'altro verso),
e, mentre Java o Visual Basic ti risolvono la cosa in modo piu`
o meno trasparente, in C, o C++, devi arrangiarti tu; in particolare,
se usi Unicode nel tuo programma, ma vuoi supportare Win95,
devi farti "a mano" tutte le conversioni -- se NON usi Unicode,
e giri su NT o CE, le conversioni se le fa "di nascosto" il sistema
operativo per tuo conto.
Le tue scelte sono dunque:
-- usare nel tuo programma caratteri di 8 bit: giri dappertutto,
    ma assai piu` lento del tuo potenziale su NT o CE;
-- usare nel tuo programma caratteri Unicode: non giri su Win95
    (se non curando tu stesso tutte le traduzioni quando servono),
    giri ma lentamente in Win98, sei molto efficiente su NT e CE;
-- rilasciare due versioni del tuo programma, una con caratteri di
    8 bit e quindi ottimizzata per Win95/Win98, una con caratteri
    Unicode e quindi ottimizzata per NT/CE.
Se non usi mai tipi "nudi" come char, char*, eccetera, ma sempre
le macro con la T (TCHAR, LPTSTR, eccetera), puoi avere la
terza opzione "gratis" -- basta compilare due configurazioni
diverse del tuo programma con e senza i #define di UNICODE
e _UNICODE!  Naturalmente devi anche usare le chiamate
"giuste" per manipolarli, questi caratteri "ambigui" -- ad esempio,
non strcpy (che funzionerebbe solo per caratteri di 8 bit!), ne`
wcscpy (che funzionerebbe solo per wchar_t, che e` il nome
ANSI C per i caratteri di 16 bit, cioe` UNicode), che sono le due
chiamate standard fornite da ANSI C, bensi` _tcscpy, che e`
una macro e si espande all'una, o all'altra, secondo i #define.
Standard C++ ti offre lo stesso tipo di opzioni per le std::string
e gli stream -- sono tutti template che possono essere poi
istanziati, o su char, o su wchar_t.  VC++5 non prevede le
macro relative, ma e` banalmente facile farsele nel proprio
codice (tipicamente negli header precompilati).  Se usi MFC,
una CString puo` rappresentare l'uno o l'altro tipo di stringa,
costruirsi sia da LPCTSTR sia dalle piu` specifiche LPCSTR
e LPCWSTR, e trasformarsi trasparentemente in una
LPCTSTR -- hai meno controllo su cosa stia succedendo,
ma forse piu` comodita` d'uso.
Grazie del chiarimento relativo a quello che stai cercando di
fare, e auguri, anche se ho qualche dubbio che il profluvio
di "subst" risultante possa lasciar funzionare bene il tutto.
Forse l'API DefineDosDevice puo` fare al caso tuo meglio
di una subst, anche se, tutto sommato, la subst si basa poi
certo su di essa -- vedi un po' tu!
Alex

certo su di essa -- vedi un po' tu!
Indagherò sicuramente anche su questa API... magari mi risparmia del lavoro
(inutile) di codifica.
        Bye
         Luca
/* togliere il "-" dall'e_mail per rispondermi direttamente oppure:
men...@writeme.com
 */
/* You can reach me online via ICQ #3652849 or via pager
http://wwp.mirabilis.com/3652849
 or 
365...@pager.mirabilis.com
 */

fossero veramente serviti 'sti interrupt ?  :-)
    __asm int 3
ad esempio, ti permette in VC++ di lanciare un interrupt 3.  Se vuoi
lanciare per qualche ragione un interrupt 16 con 27 nel registro EAX
e 15 nel registro EBX, e dopo il ritorno dall'interrupt copiare il
registro ECX nella variabile C++ pippo:
    __asm {
        mov EAX, 17
        mov EBX, 15
        int 16
        mov pippo,ECX
    }
e cosi` via.
Alex

e cosi` via.
 Beh... detto cosě suona ingannevolmente semplice anche ad una vecchia zappa
che di ASM ne capisce poco o niente come me.
 Suppongo che piangere e gridare "vojo i interrupts" non serva a niente eh...
;-)))))
 Insomma... se ho capito bene la parabola: "se vuoi fare cose a livello
assembler... usa l'assembler".  :-(
 Ed io che ero diventato cosě amico del C proprio perchč mi permetteva di
andare dall'ASM (mascherato dai suoi _intx86) fino alle piů alte vette della
grafica e dello strutturalismo.
 Vabbč... vabbč... la smetto... anche perchč il thread sta diventando quasi
solo di "cazzeggiamento". Certo che la strada per imparare č (come sempre)
costellata di spigoli (quasi tutti di Tek).  ;-)
 Grazie ancora, ad ogni modo, per i sempre preziosi hint.


grafica e dello strutturalismo.
Guarda che e` ancora cosi` anche se i bassissimi livelli devono
"togliersi la maschera" e rivelarsi per l'assembler (o linguaggio
macchina... vedi i thunk dell'ATL...) che sono.  Puoi benissimo
incapsulare quel minimo di assembler in un template, macro, o
funzione (magari inline) -- o addirittura in una struttura dati che
contiene il linguaggio-macchina del thunk (cosi` fa l'ATL...), e
tenere tutto il resto ai livelli piu` appropriati e simpatici.
(Nel mio lontano passato c'e` un Acorn "ATOM", che amavo tanto
perche` mi permetteva di mescolare al suo Basic dell'assembler
[6502] -- e` la macchina da cui si sviluppo` poi il "BBC Computer",
non che in Italia se ne siano visti molti, ma in UK si`...).
Alex

non che in Italia se ne siano visti molti, ma in UK si`...).
Nel mio ci sono un Apple ][+ (che ho programmato in ASM, Basic, C, Pascal e
Forth... tutto sempre a livelli minimi ovviamente: avevo 15/16 anni) ed un
Amiga2000 (che non ho programmato quasi per niente ma col quale ho giocato
molto).  ;-)
       Ciao
           Luca
/* sostituire _AT_ con @ nell'e_mail per rispondermi direttamente */
