 |
 |

Sommario
Internet ID
Indici di BETA
Redazione
Mailing list
Installazione
Mirror ufficiali
Licenza Pubbl. Beta
Cerca
Stampa
|
 |
 |
 |
 |
I piddle del namespace
Questo è il primo di una serie di articoli che riguardano
la possibilità di estendere le funzionalità della shell di Windows 95
e di NT 4.0. I concetti presentati non sono dei più facili da capire, per
cui non scoraggiatevi se all'inizio tutto sembrerà molto oscuro: quando
avremo finito il buio sarà pesto!
di Stefano Casini
Articolista Senior, BETA
Introduzione
Sono passati ormai piu' di tre anni dall'avvento di Windows 95; questi,
per quanto si sia rivelato fragile in alcuni suoi componenti, ed abbia
generato sentimenti di odio da parte dei puristi informatici, sta diventando
lo standard di fatto dei sistemi operativi per PC, e lo sara' almeno per
4 o 5 anni, almeno finche' si arrivera' alla fusione di 95 (o 98) con NT.
Senza voler entrare nel merito delle altre componenti del sistema operativo,
vogliamo esaminare quella parte che ha contribuito al successo di 95, ovvero
l'interfaccia grafica che si presenta all'utente, indubbiamente gradevole
all'occhio e funzionale nell'uso, e passare in rassegna i modi che permettono
di estenderne le funzionalita'.
Come tutti (o quasi) sapranno, il modulo eseguibile che si occupa di
gestire l'interfaccia di Windows 95 con l'utente si chiama explorer.exe,
e si trova nella cartella in cui viene installato Windows; in realta' explorer.exe
(che d'ora in poi chiameremo semplicemente Explorer, piuttosto che
Gestione Risorse come nella traduzione italiana) non lavora da solo, ma
viene aiutato da alcune Dynamic Link Library (DLL) e dal registro di Windows
(registry): infatti viene implementata un'architettura client-server, dove
Explorer accede, in seguito ad un evento che si verifica nel sistema
(per esempio il click con il mouse su un'icona del desktop), al registry,
legge qual e' la DLL che si occupa di gestire quel tipo di evento per quel
particolare tipo di icona, quindi chiama alcune interfacce standardizzate
presenti nella DLL che eseguono il lavoro (per esempio quello di far aprire
un menu' contestuale che contiene alcune voci piuttosto che altre).
Le interfacce esposte dalla DLL sono di tipo COM (Component Object Model),
e chiunque abbia avuto a che fare con COM e' perfettamente convinto che
piu' che un acronimo COM sia l'abbreviazione di COMPLICATO. Per rendere
la cosa piu' interessante il campo d'azione di Explorer non e' limitato
ai soli file o directory, ma comprende anche gli oggetti virtuali (folder
ed item, come ad esempio la cartella virtuale Risorse del computer, o gli
oggetti virtuali quali le connessioni di Accesso Remoto); l'insieme degli
oggetti fisici e di quelli virtuali prende il nome di namespace,
ed ogni oggetto (folder o item) all'interno del namespace e' individuato
da un PIDL (pointer to item identifier list).
Prima di procedere oltre giova ricordare che Explorer e' la
shell di Windows 95, ma non e' Windows 95, anche se si tende ad identificare
l'uno con l'altro; pertanto i pregi ed i difetti di Explorer non
vanno ad inficiare quelle che sono altre caratteristiche importanti di
un sistema operativo, quali la gestione del file system, delle porte di
comunicazione, etc., e volendo Explorer puo' essere sostituito con
un'altra shell, quale ad esempio il vecchio Program Manager, o scritta
magari da terze parti.
Il
namespace
Il namespace corrisponde praticamente al file system, solamente
che incorpora anche gli oggetti virtuali, ossia quegli item che non hanno
una corrispondenza con un preciso file o directory sul disco fisso. Se
nel disco fisso la radice del file system e' la root directory (\), nel
namespace di Explorer la radice e' il folder virtuale Desktop, ma
attenzione: se esplorate il namespace di Windows 95, troverete due
Desktop, uno che e' il folder virtuale (ed e' quello presente al livello
di gerarchia piu' alta nella combobox che si trova nella toolbar delle
finestre di Explorer), l'altro che e' una directory, situata nella directory
di Windows, al cui interno sono contenuti i file reali che avete sulla
vostra scrivania. Per fare un esempio, il Desktop virtuale contiene oggetti
virtuali quali Risorse del computer, Risorse di rete, il Cestino, ecc.,
oltre ai file ed ai collegamenti a file che si trovano nella directory
windows\desktop; e, se ancora non si e' capito, la radice del namespace
e' il folder virtuale e non la directory!
Un folder e' un contenitore di item del namespace; questi item
possono essere a loro volta dei folder, oppure degli oggetti virtuali o
dei file; in genere, ciascun folder puo' contenere solo un ben determinato
tipo di oggetti; ogni tipo di folder e' un oggetto COM che sa come enumerare
il proprio contenuto e le azioni da intraprendere in seguito agli eventi;
ed e' l'unico nel namespace a conoscere queste cose, perche' il namespace
e' gerarchico, dove il padre conosce solo i propri figli ma non ha alcuna
informazione sui nipoti. Ogni item di un folder viene univocamente identificato,
all'interno del folder che lo contiene, da un item identifier (ID),
mentre il medesimo item puo' essere identificato, sempre in maniera univoca,
a partire dalla radice del namespace (il Desktop), mediante una
item identifier list (IDL). Nella programmazione delle estensioni
di Explorer, si usa spesso il puntatore alla lista degli item identifier
(PIDL), per gli amici piddle.
Il
piddle, questo sconosciuto
Ogni item identifier (ID) viene individuato da una semplice struttura,
la SHITEMID, cosi' definita:
typedef struct _SHITEMID
{ // mkid
USHORT cb; // size of identifier, including cb itself
BYTE abID[1]; // variable length item identifier
} SHITEMID, * LPSHITEMID;
formata da un campo che ne dichiara la lunghezza, e da un campo a lunghezza
variabile che ne identifica il contenuto; il campo con la lunghezza ha
come valore la lunghezza dell'array di BYTE adID piu' il sizeof(USHORT)
(vedi fig. 1).
Figura 1
La lista degli ID viene implementata con il vecchio trucco di concatenare
una dopo l'altra piu' strutture di tipo SHITEMID, terminandola con una
in cui il campo cb ha valore zero (ed adID non c'e'); questa
la definizione della struttura ITEMIDLIST:
typedef struct _ITEMIDLIST
{ // idl
SHITEMID mkid; // list of item identifers
} ITEMIDLIST, * LPITEMIDLIST;
La lista si puo' percorrere esaminando il campo cb di ogni SHITEMID,
fermandosi quando troviamo il valore zero (deve essere uno zero a 16 bit)
(vedi fig. 2).
Figura 2
Ad esempio:
rappresenta un item identifier;
rappresenta un altro item identifier;
rappresenta un terzo item identifier;
0 |
7 |
P |
I |
P |
P |
O |
0 |
6 |
A |
L |
D |
O |
0 |
9 |
R |
O |
N |
A |
L |
D |
O |
0 |
0 |
rappresenta la item identifier list ottenuta concatenando i tre
ID.
In questo caso abbiamo messo negli ID delle stringhe, ma il contenuto
puo' essere una qualsiasi forma binaria, il cui significato e' noto solo
al folder padre degli ID.
Notate bene: la IDL deve sempre essere terminata da uno zero a 16
bit.
La memoria per i puntatori alle item identifier list (PIDL),
poiche' questi puntatori vengono passati attraverso le interfacce COM della
shell, deve essere allocata usando l'apposita interfaccia di COM, la IMalloc,
oppure la "helper function" SHGetMalloc. Usare le classiche funzioni
di Win32 quali GlobalAlloc puo' portare a risultati disastrosi.
I piddle possono essere catalogati in vari modi:
Relativo - e' il PIDL che specifica in maniera univoca un oggetto
all'interno di un certo folder del namespace;
Assoluto - e' il PIDL che specifica in maniera univoca un oggetto
rispetto all'intero namespace;
Semplice - la item identifier list contiene solo un item identifier;
Complesso - la item identifier list contiene piu' di un item
identifier.
Cosa
si trova dentro ai piddle?
Per rispondere, esaminiamo alcuni dei piddle piu' comuni che troviamo nel
nostro namespace, ricordando pero' che, a seconda del folder padre che
contiene gli item, nel piddle ci si puo' trovare di tutto, da stringhe,
a numeri binari, record o campi di database, tutto quello che passava per
la mente al programmatore che ha implementato il folder; gli esempi presentati
pertanto sono molto limitativi, utili piu' che altro a scopo didattico.
Partiamo dal nostro Desktop, e andiamo a vedere il piddle di Risorse
del computer (a proposito, per leggere i piddle bisogna scriversi un
programma che li legga, non esistono comandi diretti della shell di 95);
per risparmiare spazio e fatica, nel seguito omettero' i due byte a zero
che terminano il piddle, ma ricordate che in realta' ci devono SEMPRE essere.
Otteniamo quanto segue (in esadecimale):
byte |
valore |
0 |
14 |
1 |
0 |
2 |
1F |
3 |
0 |
4 |
E0 |
5 |
4F |
6 |
D0 |
7 |
20 |
8 |
EA |
9 |
3A |
A |
69 |
B |
10 |
C |
A2 |
D |
D8 |
E |
8 |
F |
0 |
10 |
2B |
11 |
30 |
12 |
30 |
13 |
9D |
I primi 2 byte rappresentano la lunghezza del piddle (in questo caso
e' pari a 20 byte). I 2 byte successivi rappresentano un numeretto magico
(1Fh), il cui significato e' noto solo ad Explorer, ma che possiamo ipotizzare
significhi che l'oggetto e' un folder virtuale. I 16 byte successivi rappresentano
l'identificatore della classe cui appartiene Risorse del computer,
che ritroviamo nel registry di Windows, sotto la chiave: HKEY_CLASSES_ROOT/CLSID/{20D04FE0-3AEA-1069-A2D8-08002B30309D};
quando interagiamo con il mouse sull'icona Risorse del computer,
Explorer apre il registry alla chiave suddetta, la espande e va a leggere
qual'e' il server da chiamare per gestire le azioni (in questo caso e'
shell32.dll); inoltre, nelle varie sottochiavi, trova altre informazioni
sull'icona di default, etc.
Vediamo ora il piddle del Cestino:
byte |
valore |
0 |
14 |
1 |
0 |
2 |
1F |
3 |
0 |
4 |
40 |
5 |
F0 |
6 |
5F |
7 |
64 |
8 |
81 |
9 |
50 |
A |
1B |
B |
10 |
C |
9F |
D |
8 |
E |
0 |
F |
AA |
10 |
0 |
11 |
2F |
12 |
95 |
13 |
4E |
In questo caso vediamo che anche il Cestino e' un folder, il
cui CLSID e' {645FF040-5081-101B-9F08-00AA002F954E}; dal registry vediamo
le icone usate per segnalarne lo stato di "full" o "empty", il server e'
sempre shell32.dll, infine il che Cestino aggiunge delle estensioni
autonome alla gestione sia della finestra delle proprieta', sia dei propri
menu' contestuali.
Concludiamo con il piddle del folder di Accesso Remoto:
byte |
valore |
0 |
14 |
1 |
0 |
2 |
1F |
3 |
0 |
4 |
A0 |
5 |
FF |
6 |
2C |
7 |
99 |
8 |
57 |
9 |
F5 |
A |
1A |
B |
10 |
C |
88 |
D |
EC |
E |
0 |
F |
DD |
10 |
1 |
11 |
C |
12 |
CC |
13 |
48 |
IL CLSID di Accesso Remoto e' {992CFFA0-F557-101A-88EC-00DD010CCC48},
il suo server e' rnaui.dll, che ne fornisce pure l'icona che vediamo mostrata
sul Desktop. La sottochiave ShellFolder ci segnala che e' possibile creare
dei link al folder di Accesso Remoto.
Passiamo a vedere ora il piddle di un file che mi trovo sul Desktop,
e precisamente di un file .lnk che fa da collegamento a Powerpnt.exe:
byte |
valore |
|
0 |
2E |
|
1 |
0 |
|
2 |
32 |
|
3 |
0 |
|
4 |
38 |
|
5 |
1 |
|
6 |
0 |
|
7 |
0 |
|
8 |
E9 |
|
9 |
24 |
|
A |
A4 |
|
B |
3B |
|
C |
20 |
|
D |
0 |
|
E |
50 |
P |
F |
6F |
o |
10 |
77 |
w |
11 |
65 |
e |
12 |
72 |
r |
13 |
50 |
P |
14 |
6F |
o |
15 |
69 |
i |
16 |
6E |
n |
17 |
74 |
t |
18 |
20 |
|
19 |
34 |
4 |
1A |
2E |
. |
1B |
30 |
0 |
1C |
2E |
. |
1D |
6C |
l |
1E |
6E |
n |
1F |
6B |
k |
20 |
0 |
|
21 |
50 |
P |
22 |
4F |
O |
23 |
57 |
W |
24 |
45 |
E |
25 |
52 |
R |
26 |
50 |
P |
27 |
7E |
~ |
28 |
32 |
2 |
29 |
2E |
. |
2A |
4C |
L |
2B |
43 |
N |
2C |
4B |
K |
2D |
0 |
|
Stavolta il piddle e' lungo 47 byte, il numeretto magico e' cambiato
(32h invece di 1Fh), ad indicare che non si tratta piu' di un folder ma
di un file, e cambiano anche le informazioni contenute nel piddle: i byte
da 4h a 7h contengono la lunghezza del file (138h equivalgono a 312, la
dimensione del file), i byte da 8h a Bh contengono la data di ultima modifica
del file (9 agosto 1998, ore 07.29.08; curioso come l'ora riportata sia
quella assoluta del meridiano zero, mentre la finestra delle proprieta'
del file mostra l'ora corrispondente al nostro fuso orario e tiene conto
anche dell'ora legale, riportando percio' le 9); il byte Ch contiene gli
attributi del file (il valore 20h significa che e' un file archivio; ricordiamo
che 0h e' un file normale, 1h e' a sola lettura, 2h e' nascosto, 4h di
sistema, 10h directory); il byte successivo dovrebbe contenere informazioni
sugli attributi estesi del file; infine, il piddle contiene in successione
il nome lungo (PowerPoint 4.0.lnk) ed il nome DOS (POWERP~2.LNK) del file.
Dopo aver scoperto che, per una directory, le cose sono uguali ai file,
tranne che il numeretto magico vale 31h, ed il piddle contiene valori zero
nei byte della dimensione, osserviamo il piddle di un file che punta ad
una applicazione DOS (l'orario dei treni), ovvero un .pif; e' uno di quei
tipi di file di cui Explorer non mostra mai l'estensione nelle proprie
finestre, come i .lnk ed i .url (per curiosita' provate a cercare nel registry
la parola "NeverShowExt").
byte |
valore |
|
0 |
1B |
|
1 |
0 |
|
2 |
32 |
|
3 |
0 |
|
4 |
C7 |
|
5 |
3 |
|
6 |
0 |
|
7 |
0 |
|
8 |
F8 |
|
9 |
24 |
|
A |
BA |
|
B |
B3 |
|
C |
20 |
|
D |
80 |
|
E |
49 |
I |
F |
6E |
n |
10 |
66 |
f |
11 |
6F |
o |
12 |
74 |
t |
13 |
72 |
r |
14 |
61 |
a |
15 |
2E |
. |
16 |
70 |
p |
17 |
69 |
i |
18 |
66 |
f |
19 |
0 |
|
1A |
0 |
|
Da notare la comparsa al byte Dh di un attributo esteso, a differenza
dei file "normali", e la mancanza del nome DOS del file; purtroppo non
sono in grado, al momento, di spiegarne le ragioni; trovare documentazione
sull'architettura interna di Explorer e' impossibile ai comuni mortali.
Quelli esaminati erano piddle semplici, relativi al folder
virtuale Desktop (e quindi, allo stesso tempo, assoluti, poiche'
Desktop e' la radice del namespace); vediamo adesso un esempio di piddle
contenuto in un folder diverso, per esempio quello relativo ad una connessione
di Accesso Remoto.
byte |
valore |
|
0 |
14 |
|
1 |
0 |
|
2 |
1F |
|
3 |
0 |
|
4 |
E0 |
|
5 |
4F |
|
6 |
D0 |
|
7 |
20 |
|
8 |
EA |
|
9 |
3A |
|
A |
69 |
|
B |
10 |
|
C |
A2 |
|
D |
D8 |
|
E |
8 |
|
F |
0 |
|
10 |
2B |
|
11 |
30 |
|
12 |
30 |
|
13 |
9D |
|
14 |
14 |
|
15 |
0 |
|
16 |
2E |
|
17 |
0 |
|
18 |
A0 |
|
19 |
FF |
|
1A |
2C |
|
1B |
99 |
|
1C |
57 |
|
1D |
F5 |
|
1E |
1A |
|
1F |
10 |
|
20 |
88 |
|
21 |
EC |
|
22 |
0 |
|
23 |
DD |
|
24 |
1 |
|
25 |
C |
|
26 |
CC |
|
27 |
48 |
|
28 |
19 |
|
29 |
0 |
|
2A |
0 |
|
2B |
0 |
|
2C |
2 |
|
2D |
0 |
|
2E |
0 |
|
2F |
0 |
|
30 |
1 |
|
31 |
0 |
|
32 |
0 |
|
33 |
0 |
|
34 |
0 |
|
35 |
0 |
|
36 |
0 |
|
37 |
0 |
|
38 |
54 |
T |
39 |
49 |
I |
3A |
4E |
N |
3B |
20 |
|
3C |
52 |
R |
3D |
6F |
o |
3E |
6D |
m |
3F |
61 |
a |
40 |
0 |
|
Si tratta di un piddle complesso ed assoluto, perche'
identifica l'oggetto rispetto alla radice del namespace; riconosciamo il
primo ID, lungo 20 byte, ed e' proprio il folder Risorse del computer;
ad esso segue, lungo la lista degli ID, un altro folder, anche questo gia'
visto, ed e' il folder di Accesso Remoto; notiamo che il numero
magico (byte 16h) non vale piu' 1Fh come in precedenza, ma 2Eh; questo
perche' nel primo caso il folder padre di Risorse del computer e'
il Desktop, nel secondo caso il folder padre di Accesso Remoto e'
Risorse del computer, ed ogni padre ha un diverso modo di chiamare
i figli. Chiude la lista un ID di 25 byte, che contiene, oltre a 15 byte
di significato oscuro per noi ma non per Accesso Remoto, il nome
della connessione (TIN Roma). Giova ricordare che le connessioni di Accesso
Remoto sono degli oggetti virtuali, e che non troverete sul vostro
hard disk un file che gli corrisponde.
Per finire, ecco il piddle del file fisico c:\windows\winfile.exe,
ovvero File Manager:
byte |
valore |
|
0 |
14 |
|
1 |
0 |
|
2 |
1F |
|
3 |
0 |
|
4 |
E0 |
|
5 |
4F |
|
6 |
D0 |
|
7 |
20 |
|
8 |
EA |
|
9 |
3A |
|
A |
69 |
|
B |
10 |
|
C |
A2 |
|
D |
D8 |
|
E |
8 |
|
F |
0 |
|
10 |
2B |
|
11 |
30 |
|
12 |
30 |
|
13 |
9D |
|
14 |
19 |
|
15 |
0 |
|
16 |
23 |
|
17 |
43 |
C |
18 |
3A |
: |
19 |
5C |
\ |
1A |
0 |
|
1B |
0 |
|
1C |
0 |
|
1D |
0 |
|
1E |
0 |
|
1F |
0 |
|
20 |
0 |
|
21 |
0 |
|
22 |
0 |
|
23 |
0 |
|
24 |
0 |
|
25 |
0 |
|
26 |
0 |
|
27 |
0 |
|
28 |
0 |
|
29 |
0 |
|
2A |
0 |
|
2B |
11 |
|
2C |
EE |
|
2D |
17 |
|
2E |
0 |
|
2F |
31 |
|
30 |
0 |
|
31 |
0 |
|
32 |
0 |
|
33 |
0 |
|
34 |
0 |
|
35 |
8B |
|
36 |
21 |
|
37 |
B5 |
|
38 |
AA |
|
39 |
10 |
|
3A |
80 |
|
3B |
57 |
W |
3C |
69 |
i |
3D |
6E |
n |
3E |
64 |
d |
3F |
6F |
o |
40 |
77 |
w |
41 |
73 |
s |
42 |
0 |
|
43 |
0 |
|
44 |
1B |
|
45 |
0 |
|
46 |
32 |
|
47 |
0 |
|
48 |
A0 |
|
49 |
65 |
|
4A |
2 |
|
4B |
0 |
|
4C |
18 |
|
4D |
21 |
|
4E |
60 |
|
4F |
51 |
|
50 |
20 |
|
51 |
80 |
|
52 |
57 |
W |
53 |
69 |
i |
54 |
6E |
n |
55 |
66 |
f |
56 |
69 |
i |
57 |
6C |
l |
58 |
65 |
e |
59 |
2E |
. |
5A |
65 |
e |
5B |
78 |
x |
5C |
65 |
e |
5D |
0 |
|
5E |
0 |
|
Riconosciamo nuovamente i primi 20 byte come il CLSID di Risorse
del computer, cui seguono 25 byte che identificano il drive C; quindi
23 byte individuano la directory Windows (come si riconosce dal numero
magico 31h posto nel byte 2Fh, dagli zeri nei byte della dimensione, dal
valore 10 nel byte 39h), che possiede un attributo esteso di valore 80h
nel byte 40h; infine 27 byte identificano il file all'interno della directory
(numero magico 32h, dimensione del file nei byte da 48h a 4Bh, file di
tipo archivio come ci dice il byte 50h, attributo esteso nel byte 51h).
Insomma, dopo questi esempi, dovrebbe essere un po' piu' chiaro il
ruolo che hanno i piddle nel sostituire i pathname, rispetto al classico
file system, nel namespace di Explorer.
Le
API che usano i piddle
Abbiamo detto che per estendere le funzionalita’ di Explorer bisogna ricorrere
alle interfacce COM, che non sono il massimo della semplicita’. Esistono
pero’ alcune funzioni dell’API di Windows95 che permettono ad un’applicazione
di eseguire specifici task che hanno a che fare con la shell bypassando
l’utilizzo di COM. Queste “helper function” sono riconoscibili poiche’
hanno il prefisso SH nel nome.
Di queste funzioni alcune accettano un piddle come parametro, o lo
restituiscono; in quest’ultimo caso, bisogna ricordarsi che la memoria
referenziata dal piddle restituito, una volta che non serve piu’, deve
essere liberata usando il task allocator della shell. Per fortuna, esiste
l’helper function SHGetMalloc, che permette di recuperare il puntatore
all’interfaccia IMalloc senza fare troppa fatica; la funzione sotto
riportata puo’ essere usata per liberare la memoria allocata dalle funzioni
della shell.
void LiberaMemoriaConMalloc(void * pMemoria)
{
LPMALLOC pMalloc;
// controlliamo che il puntatore non sia NULL
if(!pMemoria)
return;
// recuperiamo il puntatore all’interfaccia IMalloc
SHGetMalloc(&pMalloc);
// usiamo il metodo Free dell’interfaccia per liberare la memoria
pMalloc->Free(pMemoria);
// rilasciamo l’interfaccia IMalloc
pMalloc->Release();
}
Vediamo adesso un po’ di queste funzioni:
WINSHELLAPI void WINAPI SHAddToRecentDocs(UINT uFlags, LPCVOID pv);
Questa funzione permette di aggiungere un documento alla lista dei Dati
recenti che compare sul menu Avvio; i parametri sono due:
UINT uFlags puo' assumere valore SHARD_PATH o SHARD_PIDL,
e' un flag indicante il significato del secondo parametro passato alla
funzione;
LPCVOID pv e' il puntatore al blocco di memoria che
contiene il pathname da aggiungere alla lista, nel caso in cui uFlags
valga SHARD_PATH, oppure il puntatore ad una struttura ITEMIDLIST contenente
l'identificatore del documento all'interno del namespace, nel caso in cui
uFlags valga SHARD_PIDL. Se pv e' NULL, la funzione azzera
la lista dei Dati recenti.
WINSHELLAPI BOOL WINAPI SHGetPathFromIDList(LPCITEMIDLIST pidl,
LPSTR pszPath);
Questa funzione permette di convertire una lista di item identifier (IDL)
nel pathname equivalente del file system; i parametri sono due:
LPCITEMIDLIST pidl e’ il puntatore ad una IDL
che specifica la posizione di un file o di una directory rispetto alla
radice del namespace (piddle assoluto);
LPSTR pszPath e’ il puntatore al buffer che riceve
il pathname; la funzione fa affidamento sul fatto che il buffer sia grande
MAX_PATH byte, per cui ricordatevi di allocarlo di questa misura.
Naturalmente, se l’oggetto individuato dal piddle non fa parte del
file system, la funzione fallisce e ritorna FALSE; negli altri casi viene
riempito il buffer pszPath con il pathname del file e la funzione
ritorna TRUE.
WINSHELLAPI HRESULT WINAPI SHGetSpecialFolderLocation(HWND hwndOwner, \
int nFolder, LPCITEMIDLIST * ppidl);
Questa funzione permette di recuperare il piddle di uno dei folder "speciali" di Windows 95: questi sono sia i folder virtuali di sistema (Desktop, Pannellodi Controllo, Stampanti, Risorse di rete, Risorse del computer, Cestino), sia le directory che si trovano nel registry sotto la chiave HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders;
i parametri sono tre:
HWND hwndOwner e' l'handle ad una finestra che eventualmente mostra una dialog box o una message box;
int nFolder e'un numero che specifica quale folder "speciale" recuperare; i valori previsti sono:
CSIDL_BITBUCKET - Cestino
CSIDL_CONTROLS - Pannello di controllo
CSIDL_DESKTOP - Folder virtuale Desktop
CSIDL_DESKTOPDIRECTORY - Directory Desktop
CSIDL_DRIVES - Risorse del computer
CSIDL_FONTS - Folder virtuale Font
CSIDL_NETHOOD - Directory Risorse di rete
CSIDL_NETWORK - Folder virtuale Risorse di rete
CSIDL_PERSONAL - Directory Preferiti
CSIDL_PRINTERS - Folder virtuale Stampanti
CSIDL_PROGRAMS - Directory Programmi
CSIDL_RECENT - Directory Recent
CSIDL_SENDTO - Directory SendTo
CSIDL_STARTMENU - Directory Menu Avvio
CSIDL_STARTUP - Directory Esecuzione Automatica
CSIDL_TEMPLATES - Directory ShellNew
LPCITEMIDLIST * ppidl e' il puntatore che verra' riempito in uscita dal piddle assoluto che individua all'interno del namespace il folder "speciale" specificato dal parametro precedente.
La funzione se ha successo ritorna il valore NOERROR.
WINSHELLAPI LPITEMIDLIST WINAPI SHBrowseForFolder(LPBROWSEINFO lpbi);
Questa funzione mostra una dialog box che permette all'utente di selezionare un folder (virtuale o meno).
LPBROWSEINFO lpbi e' il puntatore ad una struttura BROWSEINFO; tra i suoi campi c'e'
LPCITEMIDLIST pidlRoot che viene riempito in entrata con il piddle della locazione del namespace che fungera' da radice per la finestra di dialogo; questo significa che l'utente della dialog box non potra' risalire al folder padre del pidlRoot, ovvero potra' navigare solo nella parte di namespace sottostante pidlRoot. Se pidlRoot ha valore NULL, la dialog box usera' come radice il folder virtuale Desktop. La dialog box e' personalizzabile tramite una funzione callback, il cui indirizzo viene riportato in uno dei campi della struttura BROWSEINFO, e si puo' indicare se la scelta del folder deve essere limitata solo a particolari tipi di folder (ad esempio solo i computer, solo le stampanti, solo le directory del file system, ecc.).
Se si seleziona un folder e si preme il pulsante OK la funzione ritorna il piddle del folder selezionato, che ricordiamo deve essere deallocato una volta che non serve piu'; se invece si preme il pulsante Annulla la funzione ritorna NULL.
WINSHELLAPI DWORD WINAPI SHGetFileInfo(LPCTSTR pszPath, DWORD dwFileAttributes,
SHFILEINFO FAR * psfi, UINT cbFileInfo, UINT uFlags);
Questa funzione recupera informazioni su di un oggetto del file system, sia esso un disco, una directory o un file.
LPCTSTR pszPath punta ad un buffer che contiene il pathname dell'oggetto. Se uFlags contiene il flag SHGFI_PIDL allora pszPath deve essere un puntatore alla ITEMIDLIST che individua univocamente l'oggetto all'interno del namespace;
DWORD dwFileAttributes contiene l'indicazione degli attributi del file di cui richiediamo le informazioni. Questo campo e' valido solo se uFlags contiene il flag SHGFI_USEFILEATTRIBUTES;
SHFILEINFO FAR * psfi e' il puntatore ad una struttura di tipo SHFILEINFO, che ricevera' le informazioni sul file;
UINT cbFileInfo contiene la dimensione, in byte, della struttura SHFILEINFO;
UINT uFlags in questo parametro si specificano i flag su quali informazioni recuperare dal file; i valori previsti sono:
SHGFI_ATTRIBUTES - recupera gli attributi del file e li mette nel campo dwAttributes della struttura puntata da psfi
SHGFI_DISPLAYNAME - recupera il display name del file e lo mette nel campo szDisplayName della struttura puntata da psfi
SHGFI_EXETYPE - la funzione ritorna il tipo di eseguibile (.COM, .BAT, .EXE per DOS, Win 16 bit o Win 32 bit) se il file e' un eseguibile
SHGFI_ICON - recupera l'handle dell'icona che rappresenta il file e l'indice dell'icona all'interno della image list di sistema. Copia queste informazioni nei campi hIcon e iIcon della struttura puntata da psfi
SHGFI_ICONLOCATION - recupera il pathname del file che contiene l'icona che rappresenta il file e lo mette nel campo szDisplayName della struttura puntata da psfi
SHGFI_LARGEICON - modifica il flag SHGFI_ICON
SHGFI_LINKOVERLAY - modifica il flag SHGFI_ICON
SHGFI_OPENICON - modifica il flag SHGFI_ICON
SHGFI_PIDL - specifica che pszPath e' un piddle invece che un pathname
SHGFI_SELECTED - modifica il flag SHGFI_ICON
SHGFI_SHELLICONSIZE - modifica il flag SHGFI_ICON
SHGFI_SMALLICON - modifica il flag SHGFI_ICON
SHGFI_SYSICONINDEX - recupera l'indice dell'icona all'interno della image list di sistema e lo mette nel campo iIcon della struttura puntata da psfi
SHGFI_TYPENAME - recupera la stringa che descrive il tipo di file, e la copia nel campo szTypeName della struttura puntata da psfi
SHGFI_USEFILEATTRIBUTES - indica che la funzione deve usare il parametro dwFileAttributes
Il valore ritornato dalla funzione dipende dal tipo di flag settati col parametro uFlags: se il flag e' SHGFI_EXETYPE il valore di ritorno contiene il tipo di eseguibile; se il flag contiene SHGFI_ICON o SHGFI_SYSICONINDEX il valore di ritorno e' l'handle all'image list di sistema che contiene l'icona; negli altri casi la funzione ritorna TRUE se ha successo, FALSE se fallisce.
Conclusioni
Abbiamo visto che attraverso il namespace Explorer allarga il classico file system agli oggetti virtuali, e come ogni oggetto del namespace sia identificato da una item identifier list (IDL), che corrisponde ad un "pathname virtuale". Per alcuni oggetti (virtuali e non) del namespace abbiamo anche visto come e' strutturata la IDL che li rappresenta, sempre tenendo conto che il significato di ogni ID e' perfettamente noto solo al folder che lo contiene. L'implementazione dei folder e degli oggetti avviene attraverso le interfacce COM di Explorer, interfacce che possono essere derivate usando DLL esterne che ne estendono le funzionalita' o creano nuove classi di folder. Le IDL vengono passate attraverso le interfacce COM usando i puntatori (PIDL), familiarmente chiamati piddle; esistono alcune "helper funcions" dell'API di Win32 che permettono di lavorare sui piddle senza passare per le interfacce COM, facilitando cosi' il lavoro al programmatore. Descritto il funzionamento di alcune di queste funzioni, rimane solo da presentare una semplice applicazione corredata di sorgenti che le utilizza: battezzata FASTDIR, permette attraverso il suo menu di accedere direttamente ad alcuni dei folder "speciali" di Explorer, e di esplorarne il namespace sottostante, nonche' di azzerare il contenuto del menu Avvio->Dati recenti. Il sorgenti possono essere compilati con Visual C++ 4.0 e versioni successive, mentre chi non ha il compilatore puo' comunque utilizzare l'eseguibile (naturalmente solo su Windows95 o NT4). La prossima volta parleremo delle piu' volte citate interfacce COM di Explorer.
Stefano Casini, ingegnere, è Articolista
di BETA dal 1995 e svolge un lavoro che non ha nulla a che fare con la
programmazione; è raggiungibile su Internet tramite la redazione
oppure all'indirizzo etngh@tin.it.
Copyright © 1998 Stefano Casini, tutti i diritti sono riservati.
Questo Articolo di BETA, insieme alla Rivista, è distribuibile secondo
i termini e le condizioni della Licenza Pubblica Beta, come specificato
nel file LPB.
BETA Rivista |
Copertina |
Sommario |
InternetID |
Informazioni |
Browser
BETA Sul Web: http://www.beta.it
|
|