Claudio Brotto

Oggetti Kernel e Terminal Server

Uno dei modi per condividere gli handle degli oggetti kernel fra processi differenti è l'utilizzo del nome dell'oggetto in questione.
 
Questo, ovviamente, richiede che il creatore dell'oggetto (P1) specifichi un nome nella chiamata alla funzione di creazione.
 
Ad esempio, se il codice del processo P1 richiama la CreateMutex come segue:
 
::CreateMutex (pSA, FALSE, "MyMutex");
 
un processo P2 può utilizzare il nome MyMutex per ottenere un handle all'oggetto mutex appena creato.
 
E se P1 e P2 sono processi appartenenti a sessioni differenti ?
Ad esempio, cosa succede se P1 viene eseguito in una sessione terminal server e P2 in un'altra ?
Oppure, senza scomodare la versione server di Windows, cosa succede su XP eseguendo i due processi da due sessioni differenti, attive grazie a Fast User Switching ?
 
[Apro e chiudo una parentesi: ho da poco scoperto che la combinazione WindowsKey + L è uno shortcut alla funzionalità di cambio rapido utente. Comodo ...]
 
Qui entrano in gioco i namespace degli oggetti kernel.
Facendo precedere al nome dell'oggetto un qualificatore di namespace, il processo creatore può indicare a Windows di creare l'oggetto nello spazio nomi della propria sessione (Local/) o in uno spazio globale (Global/). Altrettanto può (o deve ?) fare il processo che vuole ottenere l'handle dell'oggetto per nome.
 
Questo può essere fonte di bug, a volte anche "lunghi" da individuare se non si pensa subito al contesto.
 
Ieri, infatti, ho perso una mezza mattinata per questo motivo.
 
Situazione: due servizi Win32 che condividono un Memory Mapped File.
Eseguendo entrambi in versione release e come servizi, tutto funziona.
Eseguendo uno in debug e l'altro come servizio, P2 non riesce a leggere il MMF creato da P1 (da .NET, l'errore è una Win32Exception, "File not Found").
 
Il fatto è che, per dislocazioni varie in ufficio, uso spesso una connessione RDP e lavoro su un server che sta in un'altra stanza.
P1, che è stato eseguito come servizio, crea l'oggetto senza specificare un qualificatore di namespace: in quanto servizio, per default viene utilizzato il namespace Global.
P2, eseguito in debug da una sessione attivata da remoto, specifica anch'esso un nome senza qualificazione: essendo però eseguito come applicazione standard e non come servizio (in debug, ovviamente, è quello che risulta più comodo), per default i nomi vengono considerati relativi al namespace Local.
Risultato: i nomi sono differenti, P2 non trova il file e va in errore.
 
Chiaramente eseguendo entrambe le applicazioni come servizio (quindi nella sessione di sistema) il problema non si verifica.
Anzi, il problema non si verifica nemmeno eseguendo una delle due applicazioni in debug, ma dalla sessione 0 (quella attivata dal login locale sulla stazione terminal): anche in questo caso, infatti, per default il namespace è Global.
 
Quante volte ho giustificato i bachi delle mie applicazioni con: "Strano, in debug funziona ..." ?
Beh, stavolta è successo esattamente il contrario !
 
Posted: gen 28 2005, 07.44 by devlizard | with 1 comment(s)
Filed under:

Comments

devlizard said:

Ah, i namespace del kernel di Windows... io lo dico sempre che un corso di Win32 serve anche per sviluppare in .NET!
Scherzi a parte, ti consiglio il Richter (Programmazione avanzata per Windows, o qualcosa del genere) e Inside Windows Internals (ho ricevuto la quarta edizione, fresca fresca).
Così potrai dominare meglio quella belva di Windows :-)
# gennaio 28, 2005 11.12