Torna indietro   Hardware Upgrade Forum > Software > Programmazione

HONOR Magic 8 Pro: ecco il primo TOP del 2026! La recensione
HONOR Magic 8 Pro: ecco il primo TOP del 2026! La recensione
HONOR ha finalmente lanciato il suo nuovo flagship: Magic 8 Pro. Lo abbiamo provato a fondo in queste settimane e ve lo raccontiamo nella nostra recensione completa. HONOR rimane fedele alle linee della versione precedente, aggiungendo però un nuovo tasto dedicato all'AI. Ma è al suo interno che c'è la vera rivoluzione grazie al nuovo Snapdragon 8 Elite Gen 5 e alla nuova MagicOS 10
Insta360 Link 2 Pro e 2C Pro: le webcam 4K che ti seguono, anche con gimbal integrata
Insta360 Link 2 Pro e 2C Pro: le webcam 4K che ti seguono, anche con gimbal integrata
Le webcam Insta360 Link 2 Pro e Link 2C Pro sono una proposta di fascia alta per chi cerca qualità 4K e tracciamento automatico del soggetto senza ricorrere a configurazioni complesse. Entrambi i modelli condividono sensore, ottiche e funzionalità audio avanzate, differenziandosi per il sistema di tracciamento: gimbal a due assi sul modello Link 2 Pro, soluzione digitale sul 2C Pro
Motorola edge 70: lo smartphone ultrasottile che non rinuncia a batteria e concretezza
Motorola edge 70: lo smartphone ultrasottile che non rinuncia a batteria e concretezza
Motorola edge 70 porta il concetto di smartphone ultrasottile su un terreno più concreto e accessibile: abbina uno spessore sotto i 6 mm a una batteria di capacità relativamente elevata, un display pOLED da 6,7 pollici e un comparto fotografico triplo da 50 MP. Non punta ai record di potenza, ma si configura come alternativa più pragmatica rispetto ai modelli sottili più costosi di Samsung e Apple
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 12-12-2005, 21:45   #1
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
una fork per Windows [x ilsensine, ma non solo :)]

l'altro giorno sulla mailing list del corso di Laboratorio di SO arriva un niubbo e fa: "ho fatto per esercitarmi un programma che usa la funzione fork bla bla e su Windows non compila (lol ) esiste una funzione analoga alla fork su Windows?"; dopodiché arriva un altro niubbo (un po' meno niubbo del precedente però) e fa "ah bla bla bla la fork è una prerogativa dei sistemi Unix ecc. ecc.".
allora io prendo spunto e realizzo una mini-fork per Windows
non vi immaginate che sia un granché, è molto rudimentale: altro non fa che creare il processo figlio sospeso, ricopiarci tutte le sezioni non shared e non discardable impostate con permessi di scrittura oltre che di lettura, settare opportunamente il contesto del thread interrotto, ed infine riesumarlo; una fork simile funziona solo a patto che siano verificate le seguenti condizioni:
1) il programma è single-threaded
2) il programma non chiama VirtualAlloc e HeapAlloc prima della fork (dopo volendo si, ma prima no)
3) il programma non alloca handles non ereditabili prima della fork (dopo magari si, ma prima no )

comunque quel poco che fa lo fa bene
siccome ricordo che ilsensine una volta chiese a fek di spiegargli come hanno fatto quelli di Cygwin a realizzare la fork su Windows, ora la incollo qui di seguito; BTW, per l'occasione mi sono anche letto il codice della fork di Cygwin: la loro funziona un po' meglio della mia perché hanno un vantaggio: se ho ben capito come funziona questo Cygwin, si assume che un programma usi solamente le funzioni di Cygwin, quindi loro nel realizzare la fork avevano controllo sull'heap; ma per fare un bel crash anche su Cygwin è sufficiente tenere memoria di un handle non ereditabile prima di una fork

Codice:
#include <windows.h>

int fork();

int main() {
	TCHAR pszMsg[0x100];
	wsprintf(pszMsg, TEXT("questo è il processo padre, PID = %d"), GetCurrentProcessId());
	MessageBox(NULL, pszMsg, TEXT("fork on Windows"), MB_ICONINFORMATION);

	if (fork()) {
		wsprintf(pszMsg, TEXT("questo invece è il figlio, PID = %d"), GetCurrentProcessId());
		MessageBox(NULL, pszMsg, TEXT("fork on Windows"), MB_ICONINFORMATION);
	}

	return 0;
}


#define TESTFLAG(mask, flag) ((flag) == ((mask) & (flag)))

HANDLE hStarted = NULL;

__declspec(naked) void Stub() {
	SetEvent(hStarted);
	CloseHandle(hStarted);
	SuspendThread(GetCurrentThread());
}

BYTE pbJmp[5] = {0xE9};

int fork() {
	DWORD dwDummy;

	TCHAR pszFileName[0x400];
	if (!GetModuleFileName(NULL, pszFileName, 0x400)) {
		return -1;
	}

	SECURITY_ATTRIBUTES sa = {
		sizeof(SECURITY_ATTRIBUTES),
		NULL,
		TRUE
	};
	hStarted = CreateEvent(&sa, FALSE, FALSE, NULL);

	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	ZeroMemory((PVOID)&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);

	if (!CreateProcess(pszFileName, NULL, NULL, NULL, TRUE, GetPriorityClass(GetCurrentProcess()) |
		CREATE_SUSPENDED, NULL, NULL, &si, &pi))
	{
		return -1;
	}

	WriteProcessMemory(pi.hProcess, (PVOID)&hStarted, (PVOID)&hStarted, 4, &dwDummy);


	PBYTE pbInstBase = (PBYTE)GetModuleHandle(NULL);
	PIMAGE_NT_HEADERS pinth = (PIMAGE_NT_HEADERS)(pbInstBase + *(PDWORD)(pbInstBase + 0x3C));

	PVOID pvEntryAddress = (PVOID)(pbInstBase + pinth->OptionalHeader.AddressOfEntryPoint);

	DWORD dwPrevProtect;
	VirtualProtectEx(pi.hProcess, pvEntryAddress, 5, PAGE_READWRITE, &dwPrevProtect);

	*(PDWORD)(pbJmp + 1) = (DWORD)&Stub - (DWORD)pvEntryAddress - 5;
	WriteProcessMemory(pi.hProcess, pvEntryAddress, (PVOID)pbJmp, 5, &dwDummy);

	ResumeThread(pi.hThread);
	WaitForSingleObject(hStarted, INFINITE);
	CloseHandle(hStarted);

	WriteProcessMemory(pi.hProcess, pvEntryAddress, pvEntryAddress, 5, &dwDummy);

	VirtualProtectEx(pi.hProcess, pvEntryAddress, 5, dwPrevProtect, &dwDummy);


	PIMAGE_SECTION_HEADER pSecHdrs = (PIMAGE_SECTION_HEADER)((PBYTE)pinth +
		sizeof(IMAGE_NT_HEADERS));
	for (UINT u = 0; u < pinth->FileHeader.NumberOfSections; u++) {
		DWORD dwFlags = pSecHdrs[u].Characteristics;
		if (!TESTFLAG(dwFlags, IMAGE_SCN_MEM_DISCARDABLE) &&
			!TESTFLAG(dwFlags, IMAGE_SCN_MEM_SHARED) &&
			TESTFLAG(dwFlags, IMAGE_SCN_MEM_READ) &&
			TESTFLAG(dwFlags, IMAGE_SCN_MEM_WRITE))
		{
			PVOID pvSecAddr = (PVOID)(pbInstBase + pSecHdrs[u].VirtualAddress);
			WriteProcessMemory(pi.hProcess, pvSecAddr, pvSecAddr, pSecHdrs[u].Misc.VirtualSize,
				&dwDummy);
		}
	}


	BOOL InTheChild = FALSE;

	CONTEXT c;
	ZeroMemory((PVOID)&c, sizeof(CONTEXT));
	c.ContextFlags = CONTEXT_FULL;
	GetThreadContext(GetCurrentThread(), &c);

	__asm {
		call near here
here:
		pop eax
		inc eax
		mov c.Eip,eax
		mov c.Esp,esp
		mov c.Ebp,ebp
	}

	if (InTheChild) {
		return GetCurrentProcessId();
	}

	/*
	PUSH EBP
	MOV EBP,ESP
	*/

	DWORD dwFramePtr;
	__asm {
		mov dwFramePtr,ebp
	}
	DWORD dwKernel32 = (DWORD)LoadLibrary(TEXT("kernel32.dll"));
	PIMAGE_NT_HEADERS pinthKernel32 = (PIMAGE_NT_HEADERS)(dwKernel32 +
		*(PDWORD)(dwKernel32 + 0x3C));
	UINT uKernel32Size = pinthKernel32->OptionalHeader.SizeOfImage;
	while (dwFramePtr) {
		DWORD dwRetAddress = *(((PDWORD)dwFramePtr) + 1);
		if ((UINT)(dwRetAddress - dwKernel32) <= uKernel32Size) {
			break;
		}
		dwFramePtr = *(PDWORD)dwFramePtr;
	}

	DWORD dwStackPtr;
	__asm {
		mov dwStackPtr,esp
	}
	DWORD dwDelta = dwFramePtr - dwStackPtr;

	WriteProcessMemory(pi.hProcess, (PVOID)dwStackPtr, (PVOID)dwStackPtr, dwDelta, &dwDummy);


	BOOL RemoteChildFlag = TRUE;
	WriteProcessMemory(pi.hProcess, (PVOID)&InTheChild, (PVOID)&RemoteChildFlag, 4, &dwDummy);

	SetThreadContext(pi.hThread, &c);
	ResumeThread(pi.hThread);

	CloseHandle(pi.hThread);
	CloseHandle(pi.hProcess);

	return 0;
}
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 21:49   #2
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
dimenticavo: a causa di una particolarità del mio codice, il programma che chiama quella fork non può neanche chiamarla da una funzione di callback che è stata a sua volta richiamata da Kernel32.dll: altre DLL vanno bene, User32 ad esempio va bene, ma Kernel32 no
insomma sta fork fa abbastanza schifo
ma provate voi a farne una migliore su Windows

però c'è di buono che in teoria un programma che usa quella fork può anche avere un'interfaccia grafica perché gli handles delle finestre sono globalmente visibili, e quindi sarebbero validi anche nei processi figli... con l'unico problema che il processo figlio utilizzerebbe le stesse finestre del padre ci sarebbe un'attimino di interferenza
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 22:51   #3
The3DProgrammer
Senior Member
 
Iscritto dal: May 2000
Messaggi: 1459
certo ke tu e kernel32.dll vi parlate eh?


ciau
The3DProgrammer è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 22:59   #4
VegetaSSJ5
Senior Member
 
L'Avatar di VegetaSSJ5
 
Iscritto dal: Sep 2002
Città: Celano (AQ) Segno_Zodiacale: Leone Ascendente: Cammello Segni_Particolari: Quello
Messaggi: 9571



VegetaSSJ5 è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 23:17   #5
jappilas
Senior Member
 
L'Avatar di jappilas
 
Iscritto dal: Apr 2003
Città: Genova
Messaggi: 4739
bello, bello, tutta "arte che entra"

ancora inpùt, ancora...
__________________
Jappilas is a character created by a friend for his own comic - I feel honored he allowed me to bear his name
Saber's true name belongs to myth - a Heroic Soul out of legends, fighting in our time to fullfill her only wish
Let her image remind of her story, and of the emotions that flew from my heart when i assisted to her Fate
jappilas è offline   Rispondi citando il messaggio o parte di esso
Old 12-12-2005, 23:21   #6
The3DProgrammer
Senior Member
 
Iscritto dal: May 2000
Messaggi: 1459
a grandi linee l'ho capita, mi manca solo una parte:


Codice:

	*(PDWORD)(pbJmp + 1) = (DWORD)&Stub - (DWORD)pvEntryAddress - 5;
	WriteProcessMemory(pi.hProcess, pvEntryAddress, (PVOID)pbJmp, 5,      &dwDummy);
Ad occhio, &Stub-pvEntryAddress-5(?) restituisce il numero di byte che comprende la sezione tra l'entry point e la funzione Stub (di cui nn capisco la necessità di dichiararla naked) di cui vai ad effettuare una copia nel nuovo processo... o no?

ciau
The3DProgrammer è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 00:10   #7
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da The3DProgrammer
a grandi linee l'ho capita, mi manca solo una parte:


Codice:

	*(PDWORD)(pbJmp + 1) = (DWORD)&Stub - (DWORD)pvEntryAddress - 5;
	WriteProcessMemory(pi.hProcess, pvEntryAddress, (PVOID)pbJmp, 5,      &dwDummy);
Ad occhio, &Stub-pvEntryAddress-5(?) restituisce il numero di byte che comprende la sezione tra l'entry point e la funzione Stub (di cui nn capisco la necessità di dichiararla naked) di cui vai ad effettuare una copia nel nuovo processo... o no?
hum, se non hai capito quello ti manca un pezzo piuttosto grosso... ti do un aiutino: guarda il nome del buffer che conteine i dati che vado a copiare nell'altro processo, e guarda anche la dimensione di tale buffer e il valore del primo byte

ciao
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 00:14   #8
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da VegetaSSJ5



capisco lo stupore, ma come mai le lacrime?
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 09:17   #9
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Quote:
Originariamente inviato da 71104
1) il programma è single-threaded
Come mai questa limitazione? Una fork non clona i thread

Quote:
comunque quel poco che fa lo fa bene
Non dovrebbe fare molto altro, in effetti. Tieni conto che il 90% delle fork viene fatto prima di una exec (visto che nei sistemi unix non esiste un equivalente di CreateProcess), e il 9.9% sono situazioni che potrebbero essere meglio gestite tramite i thread. Direi quindi che se si intende scrivere un programma multipiattaforma che giri anche su windows, ha molto senso aggiungere quel paio di righe su #ifdef per chiamare CreateProcess oppure fork+exec a seconda della piattaforma (nascoste magari in un metodo StartNewProcess() ). Anche perché con le varie WriteProcessMemory elimini il principale punto di forza della fork (ovvero la COW), rendendo quindi estremamente inefficiente la funzione.

Grazie per la spiegazione comunque
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 09:50   #10
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Quote:
Originariamente inviato da 71104
3) il programma non alloca handles non ereditabili prima della fork (dopo magari si, ma prima no )
Anche questo non dovrebbe essere un problema, se la fork viene usata nella maniera classica (fork+exec). Anche su linux gli fd possono essere marcati "non ereditabili da una exec". In questo caso, gli handler non ereditabili dovrebbero passare inosservati/inuilizzati.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 19:31   #11
VegetaSSJ5
Senior Member
 
L'Avatar di VegetaSSJ5
 
Iscritto dal: Sep 2002
Città: Celano (AQ) Segno_Zodiacale: Leone Ascendente: Cammello Segni_Particolari: Quello
Messaggi: 9571
Quote:
Originariamente inviato da 71104
capisco lo stupore, ma come mai le lacrime?
ops hai ragione! ho dimenticato anche questo -->
VegetaSSJ5 è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 23:56   #12
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da ilsensine
Come mai questa limitazione? Una fork non clona i thread
appunto
il nuovo programma non avrà i thread del primo, avrà solo il thread primario, quindi o il programma è single threaded oppure il programmatore deve essere consapevole della limitazione.

Quote:
Non dovrebbe fare molto altro, in effetti. Tieni conto che il 90% delle fork viene fatto prima di una exec (visto che nei sistemi unix non esiste un equivalente di CreateProcess), e il 9.9% sono situazioni che potrebbero essere meglio gestite tramite i thread. Direi quindi che se si intende scrivere un programma multipiattaforma che giri anche su windows, ha molto senso aggiungere quel paio di righe su #ifdef per chiamare CreateProcess oppure fork+exec a seconda della piattaforma (nascoste magari in un metodo StartNewProcess() ).
si ma che utilità ha secondo te questa fork che non ti permette neanche di usare malloc e free??

Quote:
Anche perché con le varie WriteProcessMemory elimini il principale punto di forza della fork (ovvero la COW), rendendo quindi estremamente inefficiente la funzione.
era solo un esperimento didattico

Quote:
Grazie per la spiegazione comunque
prego
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 13-12-2005, 23:58   #13
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da ilsensine
Anche questo non dovrebbe essere un problema, se la fork viene usata nella maniera classica (fork+exec). Anche su linux gli fd possono essere marcati "non ereditabili da una exec". In questo caso, gli handler non ereditabili dovrebbero passare inosservati/inuilizzati.
il problema è il seguente:
1) il processo padre crea un handle non ereditabile per, diciamo, un file, e non lo chiude
2) fork
3) il processo figlio fa riferimento a quell'handle...

al punto 3 qualsiasi funzione API semplicemente ritorna errore, ma il processo ne deve essere "aware"; cioè, se tu mi dici che il problema esiste anche su Linux e che i programmatori che usano la fork ne sono coscienti allora va bene, volevo solo dire che è un punto da tenere presente...

Ultima modifica di 71104 : 14-12-2005 alle 00:00.
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 14-12-2005, 08:45   #14
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Quote:
Originariamente inviato da 71104
appunto
il nuovo programma non avrà i thread del primo, avrà solo il thread primario, quindi o il programma è single threaded oppure il programmatore deve essere consapevole della limitazione.
Anche la fork funziona così; un processo forkato contiene un solo thread.

Quote:
si ma che utilità ha secondo te questa fork che non ti permette neanche di usare malloc e free??
<me gnurant>
Vuoi dire che questo:
Quote:
2) il programma non chiama VirtualAlloc e HeapAlloc prima della fork
implica che non puoi chiamare malloc/free? Oh bè questo è un problema...
Quote:
3) il processo figlio fa riferimento a quell'handle...
Se l'handle non è ereditabile è corretto che il figlio lo veda chiuso
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 14-12-2005, 11:02   #15
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
Quote:
Originariamente inviato da ilsensine
implica che non puoi chiamare malloc/free? Oh bè questo è un problema...
esatto... ^^
il problema è che su Windows un processo crea uno o più heap usando HeapCreate (poi li distruggerà con HeapDestroy), e in ciascuno di questi può allocare e riallocare memoria con HeapAlloc e HeapRealloc; siccome è anche possibile enumerare tutti gli heap presenti nel processo, io potrei anche provare ad enumerarli e allocare tanti blocchi nel nuovo quanti ne vedo nel vecchio, ma non è detto che avrebbero tutti gli stessi indirizzi virtuali: servirebbero delle rilocazioni... il problema si può risolvere utilizzando VirtualAlloc al posto di HeapAlloc per allocare i blocchi dell'heap: VirtualAlloc infatti permette di specificare l'indirizzo virtuale desiderato, ma c'è un problema anche qui: gli heap in Windows sono oggetti del kernel, ovvero sono identificati da un handle, il quale ovviamente viene creato come non ereditabile; se fosse ereditabile sarebbe un gran macello perché il processo figlio accederebbe alla stessa memoria dinamica del padre senza sincronizzarsi... d'altra parte però, non essendo ereditabile, il processo figlio non vede gli handle degli heap che aveva il padre, e quindi (siccome si suppone che esso tenga memoria dell'handle dell'heap, magari all'interno del CRT di Visual C++) qualsiasi HeapAlloc, HeapRealloc ed HeapFree per lui fallirà.
in user mode insomma non si va molto lontano, a meno che non si faccia come hanno fatto su Cygwin, ovvero non si realizza un intero framework che abbia controllo su queste cose e quindi abbia anche controllo sugli handle degli heap e li possa cambiare a piacere.
quindi stavo pensando l'altro giorno a quale potrebbe essere una soluzione un po' migliore realizzata in kernel mode: in kernel mode dopo aver creato il processo si potrebbe fare un po' quello che fa Linux, ovvero ricopiare pari pari la directory e le tabelle delle pagine mettendole in protezione Copy-On-Write; il problema degli handle degli heap però rimane comunque... uqesta soluzione altro non sarebbe che una versione più efficiente della soluzione in cui uso VirtualAlloc per ricopiare gli heap nel processo figlio.
71104 è offline   Rispondi citando il messaggio o parte di esso
Old 14-12-2005, 15:06   #16
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
O bella questa...
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


HONOR Magic 8 Pro: ecco il primo TOP del 2026! La recensione HONOR Magic 8 Pro: ecco il primo TOP del 2026! L...
Insta360 Link 2 Pro e 2C Pro: le webcam 4K che ti seguono, anche con gimbal integrata Insta360 Link 2 Pro e 2C Pro: le webcam 4K che t...
Motorola edge 70: lo smartphone ultrasottile che non rinuncia a batteria e concretezza Motorola edge 70: lo smartphone ultrasottile che...
Display, mini PC, periferiche e networking: le novità ASUS al CES 2026 Display, mini PC, periferiche e networking: le n...
Le novità ASUS per il 2026 nel settore dei PC desktop Le novità ASUS per il 2026 nel settore de...
Il MacBook Pro è sempre più...
Il prezzo della Switch 2 potrebbe divent...
TikTok chiarisce il funzionamento della ...
Samsung Galaxy A07 5G: il nuovo entry le...
Realme 16 in arrivo: un mix tra iPhone A...
Domenica di follia su Amazon: iPhone 17 ...
Questo portatile HP OMEN con Core Ultra ...
Robot aspirapolvere al prezzo giusto: le...
Il nuovo M5 Max potrebbe avere una GPU p...
Pulizie automatiche al top (e a prezzo B...
Casa più calda, spese più leggere: Tado ...
Mini PC mostruoso in offerta nascosta su...
Netflix promette 45 giorni di esclusivit...
Gigabyte: un handheld? Sì, ma sol...
Samsung conferma l'arrivo di tre variant...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 03:21.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v