-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Heretics Inc. presenterar.... [ Outlaw Informativa ] issue 9, 99-12-18 ___________________ O U T L A W 9 18 December, 1999 ___________________ - A Heretics Inc. Production - "Cryptography products may be declared illegal, but the information will never be" - Bruce Schneier Ännu ett nummer släppt av Heretics. Mitt humör är ganska hyffsat nu, vilket det oftast inte brukar vara. Snart kommer Dreamhack också, jag är tyvärr ganska orolig över hur det kommer att bli, antagligen kommer det bara vara en massa gAmE gEeKs där som kör Quake turnering, det tycker jag är jävligt tråk- igt. Men det finns ju stora fördelar också: Man får träffa polare på IRC, diskutera med andra Data intresserade om Säkerhet, Unix osv och byta ut kunskaper överhuvudtaget. Jag kommer dit helt ensam så det blir en liten utmaning faktiskt, det är ju trevligt och så. Jaja, över till numret. Detta nummer kommer innehålla lite blandat information om Linux, Nya attacker, Lite fula mobil tips och lite annat tjafs. ----------------------------------------------------------------------------- Disclaimer ----------------------------------------------------------------------------- All information är helt skrivet i utbildnings syfte och vi har inga budskap eller uppmaningar att ni ska begå brott. Seriöst, jag bryr mig inte vad ni gör med informationen. Om du skulle begå brott så är ansvaret helt riktat åt din sida. ----------------------------------------------------------------------------- Medverkande ----------------------------------------------------------------------------- En enkel lista med folk som skrivit för detta nummer och hur du kan komma i kontakt med personen. Alias: diox1de Contact: keytrace@usa.net ¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ Alias: crazy-train Contact: crazy-train@telia.se ¯¯¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ Alias: Gazzaud Contact: gazzaud@operamail.com ¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ----------------------------------------------------------------------------- I N N E H Å L L S F Ö T E C K N I N G $ Staff 1:1. Editor 1:2. Disclaimer 1:3. Medverkande 1:4. Innehållsförteckning 1:5. Aktuellt 1:8. Filosofi och tankar $ Nyheter 2:1. Sun Microsystems konkurrerar inte med Linux 2:3. Säkrare SIM kort genom ny allians 2:4. Amazon sponsrar Krypto-tävling $ Phreaking och Telefoni 3:1. Hur du buggar ett rum med en mobil av: diox1de 3:2. Ett papper om GSM Systemet, del #1 av: diox1de $ Hacking, Nätverk, Säkerhet, Unix etc. 4:1. Buffer overflow i amd av: crazy-train 4:2. Linux för dumma, del #2 av: diox1de 4:3. Hur du Crackar Tolken97 av: diox1de 4:4. Andvänd Doom vid System Administration av: diox1de 4:5. Windows peer-to-peer Networking av: diox1de 4:6. Hur vi hade det på Dreamhack av: diox1de $ Programmering 5.1. Windows Programmering i C++ av: gazzaud $ Insändare 5:1. Netscape 4.05 (Messenger) kryptering 5:2. CuteFTP 3.0.2 krypterings metoder av: diox1de $ Några ord innan slutet 6:1 . Copyright 6:2 . kill -9 666 "It is insufficient to protect outselves with laws; we need to protect outseves with mathematics" - Bruce Schneier ----------------------------------------------------------------------------- Aktuellt [] ----------------------------------------------------------------------------- | --> Outlaw Informativa läggs i viloläge | |---------------------------------------------------------------------------+ | Outlaw Informativa kommer lägga sig i vilo läge, vi kommer ett tag fram | | över inte satsa så mkt på själv zinet utan mer åtenskilda textfiler.Detta | | leder till att det tar ett tag innan nästa nummer av Outlaw Informativa | | kommer ut. | +---------------------------------------------------------------------------+ | --> Kunskapsplanen forsätter | |---------------------------------------------------------------------------+ | Jag diox1de fortsätter med kunskapsplanen jag lagt upp som jag berättade | | om i förra numret (#8). | +---------------------------------------------------------------------------+ | --> Serie #2 av textfilen om abbonent växeln a345 har påbörjats | |---------------------------------------------------------------------------+ | crazy-train började skriva serie #2 i textfil serien om a345 | +---------------------------------------------------------------------------+ ----------------------------------------------------------------------------- Filosofi och tankar [] ----------------------------------------------------------------------------- Jag har förstått att många gillar Heretics men tycker inte att det är en seriös satsning. Men egentligen varför skulle det vara en ?...jag kommer ju inte släppa den här gruppen i första taget. Ingen vet vad som kommer att hän- da med Heretics egentligen. Vi kan bli en framtida företag som utvecklar säkra krypterings algoritmer eller rent av utveckla säkra telefonväxlar. Det va någon på IRC som frågada varför vi har mer Hacking och Datalogi än vad vi har Phreaking eftersom vi är en Phreaking grupp. Jag svarade att vi inte va en Phreakin grupp, vi är helt enkelt en grupp data/tele intresserade ungdomar. Det mesta av våran information är huvudsak inte skriven för er som ska läsa det utan för oss själva, dels för att det är kul och för att man lär sig och kommer ihåg det bättre som kan underlätta senare i andra fall. ----------------------------------------------------------------------------- Sun Microsystems konkurrerar inte med Linux [] ----------------------------------------------------------------------------- Sun Microsystems tillbakavisar vad företaget kallar "spekulationer" om att de vill konkurrera direkt med Linux. Dagen efter att nyheten spridits över världen om att Sun Microsystems beslutat släppa källkoden för sitt flaggskepp, operativsystemet Solaris, fritt för utvecklare (med vissa restriktioner, naturligtvis) tillbakavisar de nu att deras avsikt med planerna är att konkurrera direkt med Linux. "Linux kan ha kompabilitetsproblem att vänta i framtiden, och oavsett vilken distribution av Linux man väljer så ligger den mycket nära Sun:s teknologi" säger George Paolini, vice-VD för Sun Microsystems marknadsavdelning. Paolini avslöjade också att företaget även planerade att släppa källkoden för Java enligt samma modell som Solaris, men någon tidsplan för detta finns enligt Paolini inte. Källa: linux.idg.se ----------------------------------------------------------------------------- Säkrare SIM kort genom ny allians [] ----------------------------------------------------------------------------- Schlumberger, världens största SIM-kortstillverkare har inlett ett samarbete med Certicom, ett av världens ledande krypteringsföretag. I och med samarbet- et kan Schlumberger bygga in Certicoms senaste krypteringsteknologi ECC (Elliptic Curve Cryptography) i sina kommande SIM-kort. ECC är en kryptering som utvecklats för att passa till handdatorer, mobiltelefoner och så kallade smart cards. Fördelen med systemet är att det är energisnålt och inte heller kräver så mycket bandbredd för att hålla hög säkerhet. Högre säkerhet är ett krav både från operatörer och användare nu när WAP-teknologin med möjlighete- rna att handla till exempel aktier och utföra bankärenden direkt från mobilt- elefonen komemer. Källa: Veckans notiser om Mobil ----------------------------------------------------------------------------- Amazon sponsrar Krypto-tävling [] ----------------------------------------------------------------------------- Amazon sponsrar en krypto-tävling som går ut på att knäcka ett Krypterat meddelande och priserna blir grymma böcker så som Cryptonomicon, Applied Cry- ptography, The Code Book, och Between Silk and Cyanide. Läs mer om böckerna på: [The CODE book] http://www.amazon.com/exec/obidos/ASIN/0385495315/002-2655284-3468228 [Applied Cryptography] http://www.amazon.com/exec/obidos/ASIN/0471117099/002-2655284-3468228 [Between Silk and Cyanide] http://www.amazon.com/exec/obidos/ASIN/0684864223/002-2655284-3468228 [Cryptonomicon] http://www.amazon.com/exec/obidos/ASIN/0380973464/002-2655284-3468228 Meddelandet som ska knäckas ser ut så här: -106 047-111-70-99-24-21-25-12-53-22-56-8 038-097-34-64-242-335-51-377-183-168 038-097-34-64-380-330-115-289-273-189-56 068-486-42-23-87-434-10-468-151-345-150-494-376-415-426 038-549-53-15-1-193-121-29-109-66-28-160 Hur du gör för att vara med: Tyvärr det går inte om du inte bor eller befinner dig i USA, tråkigt tycker jag. Källa: www.amazon.com ----------------------------------------------------------------------------- Hur du buggar ett rum med en mobil [] ----------------------------------------------------------------------------- Detta är så enkelt så jag vill inte ha några klagomål helst. Hela grejen går ut på att bugga ett rum. Bla. Nokia och Ericsson är mycket bra för a tt göra detta. Du utrustar mobiltelefonen med handsfree och ställer in så att den ska svara automatiskt och ställer den i rummet du villa avlyssna och ringer upp mobilen. Huvudsyftet med det här är att enkelt kunna prata när man sitt- er i bilen osv. Men det har visats sig kunna andvändas i andra syften också. ----------------------------------------------------------------------------- Ett papper om GSM Systemet, del #3 [] ----------------------------------------------------------------------------- [Förord] Eftersom jag skrev en artikel serie om Säkerhet i GSM Systemet så tänkte jag skriva ännu en artikel serie om hur själv GSM Systemet är uppbyggt och hur det fungerar. Denna artikel serie är mycket bra att komplettera med min tidi- gare serie om Säkerhet i GSM systemet, som du kan hitta i nummer #6, #7 och #8. [Inledning] Egentligen borde alla veta vad GSM är, men jag tänker endå förklara vad det är för det finns många som saknar det som kallas i allmänbildning. GSM står först och främst för Global System for Mobile Communications. GSM är ett helt digitalt nätverk för Cellulär Mobiltelefoni. Själva mobilens abonemang är är knutet till ett kort som sitter i mobilen, ser ut som ett litet chip och kallas för SIM kort. GSM är en ersättare för de gamla analoga systemet NMT (Nordisk Mobil Telefon) GSM har förbättrat tekniken och gjort både hastigheten snabbare och ljudkvaliteten bättre. Sjävla GSM Systemet bygger på CME20 som kommer diskuteras senare. [CME20] CME20 är utvecklat av Ericsson. Den är uppbyggd enligt ETSI/GSM Tekniska Specifikationer för ett Digitalt Cellulärt Radio Nätverk. CME20 inkluderar växelcentraler, basstaions controllers, basmottagare, lokaliseringsregister och funtkioner för centralicerad andvänding och underhåll. Vilka Nätversk element består då CME20 av ? --> Växelsystemet : The Switching System (SS) Växlar och handlar alla mobiltelefon samtal. --> Basstation Systemet: The Base Station System (BSS) Här koncentreras alla radiobeslektade funktioner --> Drift och underhåll: The Operation and Support System (OSS) Drift och Underhålls funktioner vilket krävs av Nätverket. Nedan ska jag förklara vad de olika elementen har för uppgifter och hur de arbetar. [The Switching System (SS)] Växelsystemet består av 5 följande delar: ¤ The Mobile services Switching Centre (MSC) ¤ The Home Location Register (HLR) ¤ The Visitor Location Register (VLR) ¤ The Authentication Centre (AUC) ¤ Equipment Identity Register (EIR) --> The Mobile services Switching Centre (MSC) MSC tar hand om alla telefonväxelrelaterade funktioner i systemet. En Gateway funktion (GMSC) koordinerar trafiköverföringen med de fasta nätet Public Swi- tched telepone network (PSTN). MSC handlar allt som har med kanalsignalering, växelfunktioner, nätinterface och avgiftsdebitering att göra. Hela MSC är byggd i samma följd som en AXE växel. --> The Home Location Register (HLR) ----------------------------------------------------------------------------- Buffer overflow i amd [] ----------------------------------------------------------------------------- Automounter daemon (amd) har en buffer overflow i mount koden som skadar Linux och några BSD plattformer. Amd mountar automatiskt fil system i svar till försök att komma åt filer som finns i filsystemet. Att göra en lång string till AMQPROC_MOUNT proceduren, kan göra att attackeraren kan få root access. Dessa plattformer har detta problem: FreeBSD Linux Red Hat 4.2 Linux Caldera Linux Red Hat 5.2 Linux Red Hat 6.0 BSD/OS 4.0.1 BSD/OS 3.1 BSD/OS 4.0 Konsekvenser: Får rootuid Fix: Ladda hem patchen, info eller nyaste versionen av amd här: http://www.redhat.com/corp/support/errata/RHSA1999032_O1.html (Ladda bara hem am-utils.rpm senaste versionen ifrån t.ex Sunet på RedHat updates för ovanstående versioner. ftp://ftp.calderasystems.com/pub/info/security/CSSA-1999:024.0.txt http://www.bsdi.com/services/support/patches/patches-4.0.1/ ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-99:06.amd.asc ftp://info.cert.org/vert_advisories/CA-99-12-amd.html Nyhets källa: http://xforce.iis.net ----------------------------------------------------------------------------- Linux för dumma, del #2 [] ----------------------------------------------------------------------------- I dag hade jag tänkt att ta upp hur man andvänder kill för att stänga program som stannat och ta upp kommandona chmod, chown och vad Multitasking är och hur det fungerar [+] Kill samt ps [+] ==================== ps är ett komando för att lista program processer som är igång, ps står för Process Status. [+] Filrättigheter samt Filägare [+] ==================================== Det finns många olika anledningar till att du vill ändra ägare på en fil eller ändra ägare. 4 elr. r--: read-only 2 elr. -w-: write-only 1 elr. --x: execute 6 elr. rw-: read/write 5 elr. r-x: read/execute 3 elr. -wx: write/execute 7 elr rwx: read/write/execute [+] Hur ändrar man rättigheter på en fil då ? [+] ================================================= Som du ser så står det både en siffra och en bokstav. Siffrorna andvänds när du ska ändra rättigheter på en fil och bokstäverna när du visar rättigheter på en fil. # chmod 345 # ls -l --wxr--r-x 1 g1mp users 114 Oct 15 15.11 trashfile [+] Multitasking [+] ==================== Ni har säkert hört många gånger då sett folk frågat Varför Linux är så bra och dom svarar multitasking, opensource osv. Nu ska jag förklara vad Multitasking (Multikörning) är. Man kan jämnföra Linux med MSDOS (Microsoft Disk Operating System). Visst har DOS en del program för nätverk, bla. netuse, tracert, ping osv. Om du ska köra Internet i DOS så måste du ladda ner en massa program för att få ett komplett Nätverks system. Linux är också ett operativsystem som består av en kommando prompt som andvänds av en kommandotolk (shell) bla. csh, ksh, bash. I DOS andvänds skalet command.com. Ok, låt oss säga att du fått igång en Internet anslutning laddad ner en IRC klient f ör DOS osv. Det är här Linux kommer in i bilden. Du vill oftast kunna göra flera saker än att sitta på IRC och dega. I Linux finns det något som kallas Multitasking, även kallat Multikörning. Vad som menas med Multitasking är att du kan köra flera Program Processer på samma gång, det är en fördel med Linux. Sen finns det redan Nätverks applikationer till Linux som kan installeras vid Linux Setup. Du kan även lägga till dem med pkgtool (Package Tool). Hur fungerar Multitasking då? Multitasking delar upp Program Processerna i små processer och som med en viss prioritetsindelning får andvända processorn under en viss tid. Det går så pass snabbt så att vi uppfattar det som de körs sammtidigt. Denna uppdelning av Processor kraft sker med en sk. scheduler och som är en special process som ser till att processerna delas upp rättvist mellan syste- mets olika processer. ----------------------------------------------------------------------------- Hur du Crackar Tolken97 [] ----------------------------------------------------------------------------- Först och främst så är Tolken97 ett översättningsprogram som kan vara andvän- dbart om man skulle vilja översätta ord/texter osv. Tolken är programmerat av Börje Hagsten. I denna artikel hade jag tänkt förklara hur du Crackar Tolken. Ok, jag vill inte kalla det för ett Crack eftersom det är så otroligt lätt och att det inte behövs några kunskaper inom Cracking överhuvudtaget. Den filen vi ska editera är "Tolken97.ini" och det är två rader vi ska edite- ra, närmare bestämt två rader under [Program], dvs. Reg och UserName. Nedan kommer ett urklipp från en oregistrerad version av Tolken97.ini. Notera att det bara är raderna under [Program] som visas. [Program] Reg=00100 # Här kommer den första raden som ska ändras. Signal=1 LoadBas=1 LangVal=6 LangText=Engelska till Svenska FrasFil=fras0001.dat LangFile=ord0001.dat TransStyle=0 DosText=47690 MenyRad=0 StatusRad=1 RadBryt=0 Undos=250 ProgStart=0 Bubble=-1 ShowTip=0 WhatTip=0 MakeList=-1 PanelColor=8421440 ShowList=-1 CountWords=-1 CapsLocked=0 SelectLang=0 SeLang=1 UserName= # Här kommer den andra raden som ska ändras. Du ska lägga till 329716 istället för 00100 under "Regname" och sedan lägga till ett valfritt username under UserName. När den är "Crackad" så ska den se ut något i den här stilen: [Program] Reg=329716 Signal=1 LoadBas=1 LangVal=6 LangText=Engelska till Svenska FrasFil=fras0001.dat LangFile=ord0001.dat TransStyle=0 DosText=47690 MenyRad=0 StatusRad=1 RadBryt=0 Undos=250 ProgStart=0 Bubble=-1 ShowTip=0 WhatTip=0 MakeList=-1 PanelColor=8421440 ShowList=-1 CountWords=-1 CapsLocked=0 SelectLang=0 SeLang=1 UserName=Apocalyptica Ok, jag får ursäkta för en lam artikel. Men jag är inte den enda som hatar en massa fula fönster som säger att man ska registrera. Det är här Linux kommer in i bilden =) ----------------------------------------------------------------------------- Andvänd Doom vid System Administration [] ----------------------------------------------------------------------------- Fick en sida av en snubbe och tänkte skriva lite om det jag såg. Jag är helt emot spel, men det är ändå en kul grej. Ett program för Linux som dödar processer genom att springa omkring med ett vapen och döda dem helt enkelt istället för att andvända kill -9. 1981, Vernor Vinge filosoferar mycket om virtuella världar och fantasiser, i hans novell beskrivs bla. att vandra genom ett svårthittat träsk skulle kunn- a vara att gå förbi en Firewall. Detta skulle kunna vara ännu ett steg, för även datorn, typ bash är ju bara en fantasi rm -r skulle kunna vara 100101001010010101010 egentligen, men nästa steg skulle typ rm -r vara ett monster i ett spel som du ska döda. Hmm, mer tänker jag inte skriva. Tänkte bara meddela er om en liten rolig sak , om ni vill veta mer så kan ni gå till källan. Källa: ----------------------------------------------------------------------------- Windows peer-to-peer Networking [] ----------------------------------------------------------------------------- Nedan följer en artikel om hur du sätter upp ett "peer-to-peer" nätverk. peer-to-peer är alltså ett nätverk utan server. Det kan tyckas vara lamt att skriva om Windows. Men själv tycker jag att allt som har med Nätverk att göra är intressant. ¤ Koppla upp de Fysiska Nätverket ¤ Lägg till Tjänster och Protokoll ¤ Sätt ett förbestämt lokalt IP ¤ Sätt ett domainname istället för IP ¤ Dela ut mappar och skrivare ¤ Testa om det fungerar ¤ Efterord [- Koppla upp de Fysiska Nätverket -] Det här kommer jag inte skriva om så djupgående.Men det är det första steget. Här utgår jag ifrån att du ska koppla ihop två datorer, det är bara koppla kablarna först från dator 1 till hubben sen från dator 2 till hubben. Printe- rn behöver inte kopplas till hubben. Du installerar en nätverksskrivare sen endå. --> En enkel skiss: ______ |¯¯¯¯¯¯| ______ | | |Dator1|-------|EthHub|--------|Dator2| | | ¯¯¯¯¯¯ | |]----. _______ ¯¯¯¯¯¯ ¯¯¯¯¯¯ | |Printer| ¯¯¯¯¯¯¯¯¯¯¯¯¯¯ [- Lägg till Tjänster och Protokoll -] I ett Windows peer-to-peer nätverk andvänds främst netbios och TCP/IP, men även andra protokoll behövs. Jag vill ju inte att artikeln ska bli allt för grundläggande och detaljerad, men jag kan säga att du öppnar Nätverk i Kontrollpanelen för att lägga till Protokoll och Tjänster. Det som ska läggas till om det redan inte finns är: ¤ Fil- och skrivardelning för Microsoft Network ¤ IPX/SPX Kompatibelt-protokoll ¤ NetBEUI ¤ TCP/IP Lägg till tjänsterna och protokollen ovan på alla datorer som ska inkludera i Nätverket. [- Sätt ett förbestämt lokalt IP -] För att datorerna ska kunna kommunicera med varandra så krävs det att man sätter en slags identifikation på varje dator, dvs. IP nummer. Ta egenskaper för Nätverk, sedan Egenskaper för TCP > Namn på nätverkskort. Välj IP Address och klicka lite på Specify an IP Address. Skriv in en IP Add- ers, t.ex. 192.168.0.2 som är en standard för Nätverk. Om du vill veta mer kan du söka efter info om Class Nätverk. Subnet Mask ska du sätta till 255.255.255.0. [- Sätt ett domainname istället för IP -] kan du söka efter info om Class Nätverk. Subnet Mask ska du sätta till Det kan tyckas jobbigt att skriva in en ip address så for t man ska connecta till en dator. Öppna filen c:/Windows/hosts eller hosts.sam. Bläddra förbi alla kommentarer (#). Du kommer se 127.0.0.1 localhost. Lägg till dina egna IP addresser och hitta på nåt coolt domainname. t.ex. 127.0.0.1 localhost 192.168.0.3 bad_s1n 192.168.0.2 hypocrisy 192.168.0.1 mortal [- Dela ut mappar och skrivare -] För att du ska kunna ge tillgång från andra datorer att se vissa bibliotek eller devices så behöver du dela ut dem också. Högerklicka på t.ex. C enheten och välj "Dela ut" och tryck för Delad. Där kan du namnge dem och kommentera och ställa in vilken åtkomsttyp + sätta passwd på dem. Om du ska dela på en skrivare så gör du i princip samma sak. Du vandrar över till den datorn där skrivaren är inkopplad och högerklickar på den och väljer dela ut. [- Testa om det fungerar -] Gå ut i DOS och kör ping . Exempel följer nedan: C:\> ping syrgas Pinging syrgas [192.168.0.2] with 32 bytes of data: Reply from 192.168.0.2: bytes=32 time=1ms TTL=32 Reply from 192.168.0.2: bytes=32 time<10ms TTL=32 Reply from 192.168.0.2: bytes=32 time<10ms TTL=32 Reply from 192.168.0.2: bytes=32 time<10ms TTL=32 Jaupp, det funkade. [- Efterord -] Mer var det inte. Det kanske kommer eventuella tutorials där du kan lära dig IP addressering, arp och mer om tcp/ip och på ett roligt praktiskt sätt :) Har du några frågor så finns jag på DALnet (#swehack) Just det!, en sak till var det..Jag brukar inte hålla mina löften, men den här gången ska jag försöka så gott jag kan. Jag tänker nämligen skriva en tutorial eller en artikel om Nätverk och Nätverkssäkerhet i Linux. Den kompletta guiden kommer alltså innehålla hur du sätter upp en nätverk mellan flera Linux datorer och hur du sätter upp samba för att koppla ihop Windows klienter i Nätverket och till sist hur du sätter upp en dator som Firewall för att skydda ditt nätverk. ----------------------------------------------------------------------------- Hur vi hade det på Dreamhack [] ----------------------------------------------------------------------------- Jag kom dit bärande med mina grejer och lastade upp dom på ett bord och kopplade ihop alla kablar, nätverket var inte kopplat än pågrund av att dom inte hade fått hårdvaran till Nätverket. Men iafs, jag satt och pillade med Linux ett tag och såg att klockan tickade runt 13 tiden sådär,jag begav mig till informationen för att ropa upp axxezz, han kom inte första gå- ngen jag ropade upp han men däremot andra, jag flyttade bort till honom och startade Linux och började pilla igen. Sneglade mig omkring och såg att jag befann mig där folk i alla fall körde något Unix system, vilket var ganska lättande. Flera timmars väntade, inte mkt hade hänt. Jag käkade en pizza på kvällen och fortsatte pilla. Klockan slog runt 5:00 och då började switcharna komma upp på borden. Jag sprang med TP kabeln i handen och kopplade in den i switchen, precis som manslemen i vaginan :P. Först funkade det inte, och det var pågrund av att dom inte fått upp routern än. Men när den kom upp så funkade allt fint i nån timme sen pajade switchen, några timmars väntade sen funkade det igen. Klockan slog 14.00 och jag gick och sov i en timme och gick upp och ircare lite, och började träffa folk. Den första jag träffade då var dizze aka philtre som kom förbi och hälsade trevligt. Jag som tyckte synd om mig själv fick då höra hur dåligt han hade det. Han hade inget nätverkskort överhuvudtaget. Vad gjorde axxezz då ? .. han installerade om Linux 25 grr på rad och upptäckte att hans nätverksskort inte funkade, jag lånade han lite deg så ha n köpte sig ett litet fint ne2000 kort. Han kopplade in kortet och installerade Slackware (igen) och upptäckte att Lilo hade skrivit över hans boot parametrar. Han va fast i Linux!, som iofs inte var något att lida med, snarare tvärt om. Han fick dhcp att funka sen var han redan då framför IRC klienten. Jag kom ett par timmar senare. Jag köpt e också ett nytt nätverksskort. Anledning vill ni inte vet :) Tillslut var korte t och dhcp klienten fullt fungerande i mitt fina Linux system. Jag satt och pilla lite, fick även ljudet att fungera. phreedom kom över med en cd metal mp3. Så jag kopierade över lite till /dev/hda7 och började digga lite. Sen begav jag mig till kiosken och köpte en platta cola till. Tillslut, vad gjorde man på dreamhack? Man drack cola, pillade med Linux och träffade IRC folk. Den här lilla låt oss kalla historien är inte komplett, men jag hoppas att ni överlever ? ----------------------------------------------------------------------------- Windows Programmering i C++ [] ----------------------------------------------------------------------------- CCC C C + + C +++ +++ C + + CCC Windows Programmering / [#Define Version 1] [Inledning] Orsaken till den här artikeln är tristess och hos skribenten en allmän avsaknad av programmeringsdiskussioner, så ta inte alltihop på blodigt allvar. Det kan verka seriöst från en början, men allting är objektivt. Jag vet att intresset för Windoze-programmering är ganska lågt, men jag ska om jag får tid/ork skriva någonting om X11/GDK/QT-programmering istället. Den här artikeln, kan jag redan nu påpeka, kommer inte innehålla något om VC++'s klasser/metodik eller Builder. I min åsikt är det bättre att lära sig från grunden och *sedan* lära sig att använda förenklingar och eventuella utökningar. Innan vi börjar så ska jag bara dra en väldigt grundläggande sak: variablers storlek. Dessa varierar som ni säkert vet, beroende på platform. Så jag tar upp de som gäller för Windows (dvs 32-bit). unsigned CHAR 8 bits 0 till 255 CHAR 8 bits -128 127 short INT 16 bits -32,768 till 32,767 unsigned INT 32 bits 0 till 4,294,967,295 INT 32 bits -2,147,483,648 till 2,147,483,647 unsigned LONG 32 bits 0 till 4,294,967,295 ENUM 32 bits -2,147,483,648 till 2,147,483,647 LONG 32 bits -2,147,483,648 till 2,147,483,647 Dessa används uteslutande, men det finns fler. Windows har en (o)vana att använda andra variabler, allt för att kompilatorn ska kunna kontrollera att korrekt data används. Dessa faller dock tillbaks på ovanstående variablers (eller i andra fall tex float, double och dom andra) storlek. Innan vi går vidare vill jag bara påpeka att variablers storlek är ganska viktig,speciellt om ni tänker använda följande exempel, eller programmera Win32, i assembler. Därför ska ni akta er för påståenden som tex att en char och en int är lika. Sådana påstående må vara sanna nånstans, men inte här, och skulle det implementeras så kan man förvänta sig en massa onödigt krångel. Jag ska försöka att vara så detaljerad som det bara går,men känner du att det saknas något, eller vill påpeka något så gör gärna det. Även kritik, även om jag självklart kommer att ignorera alla personangrepp. Så för att ta det riktigt från början. [Hur är Windows uppbyggt?] Jag har för mig att jag tagit upp det tidigare, men en repetition skadar aldrig :-). Windows är uppbyggt för en klient-server miljö. Förväxla inte det här med någon kommunikationsmodell, även om det finns likheter. Tanken är sådan att servern (själva operativsystemet i det här fallet) ska tillhandahålla med resurser (grafiska ytor, medel för kommunikation med enheter osv) som sedan klienter (enskilda program) ska kunna använda. Denna implementering är för att skilja operativsystemet från programmen. Teoretiskt ska det betyda att när en klient kraschar så ska servern vara oberörd. Det funkar inget vidare i Windoze, men det funkar desto bättre i tex X11. Vad detta betyder är att programmet är uppbyggt annorlunda från program i DOS eller Windows 3.x. ---* Windows Multi-Tasking Windows är Multi-tasking vilket vi under lång tid blivit varse. Medan DOS program var ganska statiska (om programmet inte gjorde någonting, så hände ingenting och skulle det hända någonting så var det upp till program- met att se till att det hände) så är Windows program dynamiska. Även om programmet inte gör något, skickas data till det, andra program utför saker och så vidare. Vad betyder detta programmeringsmässigt? Jo det betyder att Windows måste hela tiden ha en möjlighet att återge händelser till ditt program, detta sker igenom en sk Message-Queue. När Windows vill kommunicera med ditt program, skickar den ett message, vilket placeras i en kö, och som sedan Windows förväntar sig att programmet ska behandla. Meddelanden är helt enkelt en struktur, kanske ska tilläggas. Jag går närmare in på detta utbyte längre fram. ---* Windows API (Application Programming Interface) enkelt en struktur, kanske ska tilläggas. Jag går närmare in på detta utbyte Det interface som används för att kommunicera med Windows och andra program. Lite grovt skulle man kunna säga att det är en vidareutveckling av INT's. Så eftersom ni nu genast skaffat denna felaktiga uppfattning, ska jag dra skillnaderna. Medan INT's var deklarerade i operativsystemet självt är API en samling funktioner i olika .DLL's, Dynamic Link Libraries. Själva samlingen kan därför enkelt expanderas med funktioner som inte operativsyst- operativsystemet själv handhar, utan som är från olika program. Den grundläggande kommunikationen med enheter (som INT's hade hand om) ligger inte hos API, utan dessa är istället ytterligare ett lager, allt för att underlätta kommunikationen, och säkert även utvecklingen av program. Ska också påpekas att Windows använder en 32-bit flat memory model till skillnad från DOS, men det har jag tagit upp tidigare och en repition är överflödig. Så för att ni inte ska dö av tristess innan artikeln ens börjat så ska jag skriva ett litet HelloWorld program. Dom brukar vara populära :-). NOTeringar innan exemplet: Alla variabler som börjar på h är generellt handles, för en beskrivning av variabel-prefix se slutet. #include /* Självklart */ LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); /*Funktionsdefinition för att vi ska slippa errors pga att vi placerar funktionen sist. */ char szWinName[] = "MinWinKlass"; /* Vad våran Window-klass ska heta. Mer om det under genomgången */ int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode) { HWND hwnd; MSG msg; WNDCLASS wcl; /* En titt på ovanstående skadar inte. */ /* Okey, så låtom oss tala om hur våran fönster-klass ska vara. Det gör vi igenom att manipulera medlemmarna i den (WNDCLASS) wcl vi just deklarerat. */ wcl.hInstance = hThisInst; /* handle till våran instans. */ wcl.lpszClassName = szWinName; /* Namnet på våran klass */ wcl.lpfnWndProc = WindowFunc; /* Den CallBack window-funktion som sedan ska ta hand om de meddelanden (messages) som Windows skickar till vårt program */ wcl.style = 0; wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* standardikon hämtas med LoadIcon */ wcl.hCursor = LoadCursor(NULL, IDC_ARROW); /* ditto (fast pekare givetvis ;-) */ wcl.lpszMenuName = NULL; /* ingen meny den här gången */ wcl.cbClsExtra = 0; wcl.cbWndExtra = 0; /* Det var dom grundläggande medlemmarna det. Uhm. Just det, kanske ska tala om färg på bakgrunden också */ wcl.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); /* detta gör vi igenom att lämna tillbaks handle'n till en vit pensel med GetStockObject(). */ if(!RegisterClass(&wcl)) return 0; /* så försöker vi registrera vår fönsterklass så att Windows ska veta vad vi pratar om sedan när vi kommer att referera till den. Skiter det sig här är det allvarligt och det är stort sett bara att avlsuta. */ /* sådärja men eftersom att mickla med en klass inte åstadkommer nånting (mer än att se till att det här programmet funkar ;-) så ska vi också skapa ett fönster (wheee)... */ hwnd CreateWindow( szWinName, /* Vilken window-klass vi ska använda */ "HelloWorld Example", /* vad som ska stå i title-bar'en */ WS_OVERLAPPEDWINDOW, /* vilken stil vi ska ha på vårat fönster */ CW_USEDEFAULT, /* X koordinat, låt windows bestämma */ CW_USEDEFAULT, /* Y koordinat, ditto */ CW_USEDEFAULT, /* bredd, ditto */ CW_USEDEFAULT, /* höjd, ditto */ HWND_DESKTOP, /* Förälder? Skrivbordet. Mer om det senare. */ NULL, /* ingen meny */ hThisInst, /* vilken instans av programmet */ NULL); /* inga extra parametrar */ /* Sådär ja. Ett fönster. Men eftersom vi inte angett WS_VISIBLE som stil, så syns det inte ännu. Därför så visar vi det, och passar på att uppdatera */ ShowWindow(hwnd, nWinMode); UpdateWindow(hwnd); /* Nu, ytterligare en viktig del, våran messageloop. Den kommer att fånga upp alla messages som kommer att riktas till vårat program och sedan skicka dom till våran Window CallBack funktion (WindowFunc). Loopen avslutas när 0 lämnas, vilket betyder att programmet ska avslutas. */ while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); /* lämna tillbaks kontrollen till Windows */ } return msg.wParam; } /* Dags för våran CallBack funktion. */ LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_DESTROY : PostQuitMessage(0); /* kommer göra så att våran MessageLoop får 0 och hela programmet avslutas */ break; default : /* alla andra meddelanden hamnar här men det är ju logiskt */ return DefWindowProc(hwnd, message, wParam, lParam); /* Låt Windows avgöra hur meddelandet ska hanteras, slags standardbehandling */ } return 0; } Känner ni igen programmet BTW? Bra, då har ni läst min tidigare, lite spartanare text om grundläggande Windows programmering. Jag är hemskt ledsen om det blir något av en upprepning. Det får ni tåla.Jag förutsätter att alla vet hur man använder klasser, switch-satser och liknande eftersom det är grundläggande C++. Annars får ni väl skälla på mig :-). Programmets exekvering börjar vid WinMain() och får från Windows lite data som kan vara användbart. hThisInst refererar till nuvarande instans, och hPrevInst till den förra. Används om man tex vill förhindra att flera instanser av ens program finns samtidigt. lpszArgs är en pekare till en sträng som innehåller all command-line data.nWinMode innehåller en parameter som säger hur Windows vill att ditt program först ska visas. Går att bortse ifrån. szWinClassName[] innehåller vad än vi månde vilja kalla våran Window-klass (WNDCLASS). Strängen används sedan för att referera till just denna klass. hwnd eller hWnd om ni hellre vill det, är en handle till vårat fönster. Vid alla operationer igentemot det måste vi ha denna handle. Även för att kunna påverka andra fönster måste vi ha deras handle's, men mer om hur man får fram dessa senare. Grundläggande faktum: Ingen handle, ingen påverkan. wcl behöver jag väl inte gå igenom, eller hur? Bra. Däremot kan vi titta lite närmare på LoadIcon & LoadCursor. HICON LoadIcon(HINSTANCE hInst, LPCSTR lpszName); HCURSOR LoadCursor(HINSTANCE hInst, LPCSTR lpszName); hInst anger instansen för den modul som innehåller resursen, eftersom vi hämtar en standardresurs anger vi NULL. lpszName identifierar resursen. Exempel på standardikoner (\include\windows.inc) IDI_APPLICATION 32512 IDI_ASTERISK 32516 IDI_EXCLAMATION 32515 IDI_HAND 32513 IDI_QUESTION 32514 Exempel på standardpekare (\include\windows.inc) IDC_ARROW 32512 IDC_CROSS 32515 IDC_IBEAM 32513 IDC_WAIT 32514 Som tidigare påpekats skaffar vi oss en vit bakgrund igenom att lämna en handle till en pensel (brush) som är vit. Detta görs med GetStockObject() som används för att hämta standardresurser. Orsaken till (HBRUSH) konverteringen är för att GetStockObject() ser ut såhär: HGDIOBJ GetStockObject(int object); Exempel på standardpenslar (\include\windows.inc) BLACK_BRUSH 4 DKGRAY_BRUSH 3 HOLLOW_BRUSH 5 LTGRAY_BRUSH 1 WHITE_BRUSH 0 När vi skapade vårat fönster använde vi en ganska extensiv stil, WS_OVERLAPPEDWINDOW, men vi kan vara mycket petigare om vi vill. Följande stilar kan OR'as ihop för att åstadkomma en mer användardefinierat fönster. Exempel på fönsterstilar (\include\win32\winuser.h) WS_BORDER(0x80) -- Enkel ram WS_OVERLAPPED(0x00) -- Fönster med border. WS_MAXIMIZEBOX(0x01) -- Fönster med Maximize-ruta WS_MINIMIZEBOX(0x02) -- Fönster med Minimize-ruta WS_SYSMENU(0x08) -- System meny WS_CAPTION(0xC0) -- Alt WS_BORDER | WS_DLGFRAME WS_THICKFRAME(0x04) -- Fet border WS_OVERLAPPEDWINDOW(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) Än så länge har jag inte bidragit med så mycket nytt, men ha lite tålamod, det kommer. Först bara en snabb förklaring av WM_DESTROY. Detta är ett meddelande som skickas av Windows när din applikation håller på att avslut- as. Så inom denna case så ska förslagvis all upprensning ske så att programmet kan avslutas 'rent'. Släpp låsta resurser, frigör minne och snygga upp efter programmet. Observera att WM_DESTROY postas *efter* det att fönstret redan tagits bort, avslutning har på detta vis redan påbörjats.Vill man ingripa tidigare i avslutningsprocessen (som tex fråga om användaren verkligen vill avsluta) ska man använda sig av WM_CLOSE. I DefWndProc() anropar WM_CLOSE helt enkelt DestroyWindow() som i sin tur genererar ett WM_DESTROY meddelande, som anropar PostQuitMessage() som i sin tur genererar ett WM_QUIT meddelande. WM_CLOSE -> DestroyWindow() -> WM_DESTROY -> PostQuitMessage() -> WM_QUIT Program har också så att dom frågar 'Vill du verkligen avsluta?'. Det kan vi lägga till. Då ska vi använda oss av MessageBox() som ser ut på detta vis: int MessageBox(HWND hWnd, LPTCTSTR lpText, LPTCTSTR lpCaption, UINT uType); Exempel på typer för MessageBox'es: MB_ABORTRETRYIGNORE MB_ICONASTERISK MB_ICONERROR MB_ICONEXCLAMATION MB_ICONHAND MB_ICONSTOP MB_ICONINFORMATION MB_ICONQUESTION MB_ICONWARNING MB_OK MB_OKCANCEL MB_RETRYCANCEL MB_YESNO MB_YESNOCANCEL Det går i den mån det är praktiskt att använda fler typer. Tex: MessageBox(hwnd,"Vill du verkligen avsluta?","Avsluta",MB_YESNO | MB_ICONQUESTION); för våran avslutningsfrågare. Return-värden är: IDABORT, IDCANCEL, IDIGNORE, IDNO, IDYES, IDRETRY och IDOK, med reservation för att jag kan ha glömt någon. case WM_DESTROY : PostQuitMessage(0); break; case WM_SYSCOMMAND : if(wParam == SC_CLOSE){ if(MessageBox(hwnd,"Vill du verkligen avsluta?", "Avsluta",MB_YESNO) == IDYES) PostQuitMessage(0); } else return DefWinProc(hwnd,message,wParam,lParam); break; En kort förklaring av MB_YESNOCANCEL Det går i den mån det är praktiskt att använda fler typer. Tex: MessageBox(hwnd,"Vill du verkligen avsluta?","Avsluta",MB_YESNO | MB_ICONQUESTION); för våran avslutningsfrågare. Return-värden är: IDABORT, IDCANCEL, IDIGNORE, IDNO, IDYES, IDRETRY och IDOK, med reservation för att jag kan ha glömt någon. case WM_DESTROY : PostQuitMessage(0); break; case WM_SYSCOMMAND : if(wParam == SC_CLOSE){ if(MessageBox(hwnd,"Vill du verkligen avsluta?", "Avsluta",MB_YESNO) == IDYES) PostQuitMessage(0); } else return DefWinProc(hwnd,message,wParam,lParam); break; En kort förklaring av WM_SYSCOMMAND kan vara på sin plats för alla er som inte orkar kolla upp saken. Detta meddelande genereras när någonting väljs antingen från ett fönsters system-meny eller snabbsystem-knapparna till höger. Vågar man ta med lite kass ASCII? .-------------------------------------------------. |Ikon | Program-titel |Min|Max|Close| |_____|_____________________________|___|___|_____| | \|/ | | System-meny Snabbval Exempel på SYSCOMMAND-alternativ SC_CLOSE 0x0F060 Stäng, avsluta fönstret SC_DEFAULT ? Dubbelklick på system-menyn SC_MAXIMIZE 0x0F030 Maximera SC_MINIMIZE 0x0F020 Minimera SC_RESTORE 0x0F120 Återställ SC_ICON SC_MINIMIZE SC_ZOOM SC_MAXIMIZE Jaja, det där kan ni säkert redan. Vi går över till kontroller. Dessa är pre-definierade fönster-klasser och sonika behöver vi inte skapa nya klasser utan kan åberopa dem direkt med CreateWindow(). Vi lägger detta under initierings-fasen av ovanstående program, nämligen i WM_CREATE. RECT rect; HWND hButton; ---- switch(message) { case WM_CREATE : hButton = CreateWindow("BUTTON", "Quit", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 65, 25,hwnd,NULL, hThis Jaja, det där kan ni säkert redan. Vi går över till kontroller. Dessa är pre-definierade fönster-klasser och sonika behöver vi inte skapa nya klasser utan kan åberopa dem direkt med CreateWindow(). Vi lägger detta under initierings-fasen av ovanstående program, nämligen i WM_CREATE. RECT rect; HWND hButton; ---- switch(message) { case WM_CREATE : hButton = CreateWindow("BUTTON", "Quit", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 65, 25,hwnd,NULL, hThisInst, NULL); if(hButton == NULL) MessageBox(hwnd, "Kunde inte skapa knapp.", "Error",MB_OK); break; case WM_DESTROY : PostQuitMessage(0); /* kommer göra så att våran MessageLoop får 0 och hela programmet avslutas */ break; default : /* alla andra meddelanden hamnar här men det är ju logiskt */ return DefWindowProc(hwnd, message, wParam, lParam); /* Låt Windows avgöra hur meddelandet ska hanteras, slags standardbehandling */ } return 0; } Hmmmm... Ingen vidare placering, eller hur? Nåja. Låt oss rätta på det innan vi går vidare med att få knappen att fungera. (Observera RECT rect; som vi deklarerade i exemplet ovan, men som egentligen inte används förrens nu). case WM_CREATE : GetClientRect(hwnd, &rect); hButton = CreateWindow("BUTTON", "Quit", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, (rect.right / 2) - 30, rect.bottom-26, 65, 25,hwnd,NULL, hThisInst, NULL); if(hButton == NULL) MessageBox(hwnd, "Kunde inte skapa knapp.", "Error",MB_OK); break; Koordinaterna *borde* göra så att knappen hamnar i mitten-längst-ner, stämmer inte det så korrigera koordinaterna tills knappen är där du vill ha den. Innan jag glömmer, såhär ser RECT ut: typedef struct _RECT { LONG left; LONG top; LONG right; LONG bottom; } RECT; GetClientRect() hämtar datan för den rektangel som är klient-området på ett fönster. Den är också relativ till sig själv så left & top är alltid 0. För att hämta ett fönsters rektangel relativ till skärmen används GetWindowRect(), men bägge fungerar på samma sätt. Men varför funkar inte knappen? Helt enkelt därför att vi låter Windows hantera dess funktionalitet ;-). Allvarligt, så beror det på att vi överlåter de meddelanden som knappen generar till DefWndProc() som helt sonika inte gör något åt dem. Så låt oss ändra på det. De flesta kontroller skickar sk notify-messages till sina föräldrar när något händer dem, eller när de förväntar att något ska hända. Notify-messages går igenom WM_COMMAND, så vi fångar upp dessa. HWND hwndCtl; long wNotifyCode; ---- case WM_COMMAND : hwndCtl = (HWND) lParam; wNotifyCode = HIWORD(wParam); if(wNotifyCode == BN_CLICKED) PostQuitMessage(0); break; Trevligt. Nu kan vi avsluta vårat program med knappen. Fast det finns en liten skavank i det här programmet. Lägger vi till ytterligare en knapp, så kommer inte programmet att göra någon skillnad på dem och båda kommer därför att skicka ett PostQuitMessage(). Det vill vi ju inte. Så vi modifierar den lite. HWND hwndCtl; long wNotifyCode; case WM_COMMAND : hwndCtl = (HWND) lParam; wNotifyCode = HIWORD(wParam); hButton = GetWindow(hwnd, GW_CHILD); if((wNotifyCode == BN_CLICKED)&&(hwndCtl==hButton)) PostQuitMessage(0); break; Nu kommer bara den knapp som skapats först att avsluta programmet. En liten förklaring kan nog vara på sin plats. GetWindow() hämtar en fönsterhandle som har en specifik relation till en annan fönsterhandle. I det här fallet, barnet till vårat huvudfönster, vilket råkar vara knappen, eftersom vi skapade den med WS_CHILD. HWND GetWindow(HWND hWnd, UINT uCmd); Exempel på relationer i GetWindow(): GW_CHILD 5 GW_HWNDNEXT 2 GW_HWNDPREV 3 GW_OWNER 4 Nu är det ju så att våran knapp har en ganska statisk position. Den placeras när fönstret skapas, men det är allt. Sedan sitter den bara där. Det fixar vi igenom att fånga upp WM_SIZE (jupp, ni gissade rätt, skickas när storleken på ett fönster ändras). Så vad ska vi göra i WM_SIZE? Känner du att du börjar få grepp om det hela, så pröva själv att lista ut hur det ska se ut, målet är en knapp som dynamiskt flyttar sig efter hur stort fönstret är. Därav att jag placerade den i mitten :-). Under tiden kan jag ta upp relationer mellan fönster som vi var inne på tidigare. En Förälder kan ha hur många Barn som helst, men ett Barn kan bara ha en Förälder (inga familjevärden där inte ;-). Förutom detta faktum finns det vissa andra saker som gäller Förälder-Barn relationen. Ett Barn är begränsat av sin Förälders klient area, dvs ett Barn kan inte ritas utanför sin Förälder. Istället blir barnet 'clipped' som det kallas, arean som egentligen är utanför Föräldern ritas helt enkelt inte. Däremot kan (om inte WS_CLIPCHILDREN angetts) Föräldrar rita över sina Barn. Syskon kan också rita över varann så länge inte ett av syskonen har WS_CLIPSIBLINGS. Relationer mellan fönster kan ändras med tex SetParent(). Andra funktioner gällande relationer är GetParent(), IsChild() och EnumChildWindows(). Den sistnämnda kan kräva en förklaring. BOOL EnumChildWindows( HWND hWndParent, WNDENUMPROC lpEnumFunc, LPARAM lParam); Denna funktion förpassar alla Barn-handle's till en specifierad CallBack funktion, lpEnumFunc. lParam är en applikationsdefinierad parameter som kan skickas med som ytterligare argument. Denna funktion är mycket mer pålitlig än att anropa GetWindow() i en loop då den inte påverkas av yttre påverkan på Barnen. När en Förälder ska förstöras skickas en WM_DESTROY till alla Barn. Som tidigare påpekats skickar system-definierade Barn sk Notify messages till sina Föräldrar, men det är viktigt att veta att alla messages skickas direkt till Barnen, utan att processeras av Föräldern. Enda undantaget är om ett Barn har blivit Disabled, Föräldern mottar då alla input messages som skulle förpassats till Barnet för att kunna avgöra när det återigen ska bli Enabled. ... För att återigen återgå till våran knapp. Här är ett exempel på hur det skulle kunna se ut. case WM_SIZE : hButton = GetWindow(hwnd, GW_CHILD); GetClientRect(hwnd, &rect); MoveWindow(hButton, (rect.right / 2) - 30, rect.bottom-26, 65, 25, TRUE); UpdateWindow(hwnd); break; ... ---* Leka med musen (det vill vi alla... ) Eftersom Windows i högsta möjliga mån faller tillbaks på musen så kan det vara passande att gå igenom hur den fungerar och vad man kan tänkas ha för kul med den. Istället för att gå igenom något oproduktivt exempel där någon text skrivs ut där muspekaren befinner sig, ska vi istället börja direkt med att göra någonting nyttigt med den. Vissa applikationer har som bekant en bakgrund som är en interaktiv del av programmet självt, även om det i många fall bara handlar om att byta just utseendet på bakgrunden. Men jag ska försöka visa hur detta går till, igenom den flytande meny som ska dyka upp när man höger-klickar inom ett fönsters klient-area. Nu dyger det dock upp en kompilator-kompabilitets fråga, nämligen med hur resurser inkluderas i ett program. I Borlands kompilator är det bara en fråga om att inkludera en text-fil som heter *.rc. Hur det går till med just eran kompilator är en sak som ni själva får utforska. Men med alla 'bloated' kompilatorer ska det inte vara något större problem. Kör ni direkt översättning till assembler blir det lite jobbigare, observa detta, men inte svårare eftersom assembler har den mest genuina approachen av alla. Eftersom vi bara ska (iaf just nu) ha en meny så kan man i viss mån komma runt användandet av .rc filen. Men det blir till utövarens eget infinitum indoles. Så vi börjar med att lägga till våran lilla popup-meny till en .rc fil. POPPIE MENU { POPUP "PopupMeny" { MENUITEM "&Alt 1",601 MENUITEM "&Alt 2",602 } } Klar? Aurum. Vi ska nu se till att den kommer till användning också. För att skapa en flytande popup meny kommer vi att använda TrackPopupMenuEx(). BOOL TrackPopupMenuEx(HMENU hmenu, UINT fuFlags,int x, int y, HWND hwnd, LPTPMPARAMS lptpm); Frågan är nu när vi ska skapa denna meny. Ett förslag är WM_RBUTTONDOWN. Eftersom ingen har möjlighet att i denna redan övergågna presens, protestera så använder vi det. POINT pt; HMENU hMenu, hSubMenu; ---- case WM_RBUTTONDOWN : pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); ClientToScreen(hwnd, &pt); hMenu = LoadMenu(hInst, "POPPIE"); hSubMenu = GetSubMenu(hMenu, 0); TrackPopupMenuEx(hSubMenu, 0, pt.x, pt.y, hwnd, NULL); DestroyMenu(hMenu); break; Egentligen inte så mycket konstigheter men vi går igenom det ändå för säkerhets skull. POINT är en struktur som innehåller x & y positionen av en punkt. typedef struct tagPOINT { LONG x; LONG y; } POINT; I deklarationen av WM_RBUTTONDOWN ser vi att lParam innehåller positionen för pekaren när meddelandet postas. Sedan använder vi ClientToScreen() vilket kan verka något kryptiskt, men är fullt logiskt när man vet var det handlar om. BOOL ClientToScreen( HWND hWnd, LPPOINT lpPoint); ClientToScreen() översätter helt enkelt koordinaterna från en punkt, relativ till ett fönsters klientområde till skärmkoordinater. Sedan laddar vi våran menu från nuvurande instans' resurser med LoadMenu(). Vi använder oss av den identifierare som vi använt oss av i .rc'n. HMENU LoadMenu( HINSTANCE hInstance, LPCTSTR lpMenuName); BOOL DestroyMenu(HMENU hMenu); Efter detta plockar vi fram våran sub-meny, som vi sedan använder när vi anropar TrackPopupMenuEx(). Hmmm. Den deklarationen hade jag redan haft med, så var det ja. Eftersom våran meny-resurs inte längre behövs, frigör vi den med DestroyMenu(). Så långt har vi en meny. Men den åstadkommer inte vidare mycket. Varför inte? (Får jag höra i kör nu:) Därför att meddelandena som menyn genererar hamnar hos DefWndProc(). Eller om ni sparat tidigare ändringar så ignoreras de totalt (de går nämligen igenom WM_COMMAND). Men innan vi går vidare och ger våran lilla popup-meny en orsak för sin existens så ska vi gå in lite som hastigast på några system definierade funktioner som finns för att programmeraren ska slippa behöva ha med vissa grundläggande uppgifter i sitt program. En av dessa är GetOpenFileName(). BOOL GetOpenFileName(LPOPENFILENAME lpofn); Denna struktur (LPOPENFILENAME) är stor och smått otymplig, men jag ska, så gott jag kan, försöka redovisa hur den används. Så vi skriver om våran WM_COMMAND. Observera att IDM_ALT1 kan bytas ut mot 601 eller om vi ska använda den, så måste vi ha en #define IDM_ALT1 601, antingen tillsammans med includes'en i början, eller i en separat .h fil (som givetvis måste länkas till projektet i Borland). char szFileHolder[256]; bool resp; ------ case WM_COMMAND : switch(LOWORD(wParam)) { case IDM_ALT1 : OPENFILENAME ofn; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = hInst; ofn.lpstrFilter = "All files\0 *.*\0Bitmap Files\0*.bmp\0\0"; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = NULL; ofn.nFilterIndex = 0; szFileHolder[0]='\0'; ofn.lpstrFile = szFileHolder; ofn.nMaxFile = NULL; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = "Välj fil..."; ofn.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES; resp = GetOpenFileName(&ofn); break; default : break; } UpdateName(hwnd); } Jahopp. För att ni nu inte ska bli helt uppgivna över denna struktur så får jag väl gå igenom lite mer detaljerat. -- lStructSize = sizeof(OPENFILENAME); Deklarerar att storleken på vår struktur är lika stor som en OPENFILENAME struktur. Se den som mer eller mindre standard. -- hwndOwner = hwnd; Vilket fönster som ska 'äga' dialogen när den skapats. -- hInstance = hInst; Vilken instans det är som vill skapa dialogen. -- lpstrFilter = "All files\0 *.*\0Bitmap Files\0*.bmp\0\0"; De filter alternativ som ska finnas och deras motsvarande pattern. Observera de NULL som används för att separera dem åt och att den avslutas med NULLNULL. ---- lpstrCustomFilter = NULL; nMaxCustFilter = NULL; Dessa använder vi inte. Har samma användningsområde som lpstrFilter, och fungerar på liknande vis (fast sparas från en dialog till nästa). nMaxCustFilter anger längden på lpstrCustomFilter. -- nFilterIndex = 0; Anger vilket filter som ska vara aktivt när dialogen skapas. Anges noll så används lpstrCustomFilter, är denna NULL, så används första paret i lpstrFilter. -- szFileHolder[0]='\0'; lpstrFile = szFileHolder; När dialogen skapas anger denna medlem vilken fil som ska användas vid initialiseringen, NULL anger att en sådan inte behövs. När dialogen avslutats innehåller den filen som valts av användaren. -- nMaxFile = NULL; Anger storleken på lpstrFile om denna används. -- lpstrFileTitle = NULL; En buffer som mottar titeln på den valda filen. -- nMaxFileTitle = 0; Maxlängden på lpstrFileTitle, ignoreras om denna är NULL. -- lpstrInitialDir = NULL; Vilken katalog som ska vara öppnad när dialogen skapats. Vid NULL så används systemkatalogen. -- lpstrTitle = "Välj fil..."; Titeln på dialogrutan. Om NULL används systemdefinitionen ("Öppna" alt "Spara"). -- Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES; Vilka flaggor som ska gälla. Exempel på flaggor till GetOpenFileName(): OFN_ALLOWMULTISELECT 0x200 Tillåt att flera filer väljs. Ifall den används så pekar lpstrFile till en buffer som innehåller den aktiva katalogen och alla valda filer. Dessa separeras med space (' '). För de nya Explorer dialogerna används '\0' som separator och buffern avslutas med '\0\0'. OFN_CREATEPROMPT 0x2000 Anger att dialogen ska fråga användaren om denne vill skapa en icke-existerande fil. OFN_EXPLORER 0x80000 Skapa en 'Explorer-lik' dialog. OFN_FILEMUSTEXIST 0x1000 Den valda filen måste existera, användaren kan alltså inte skriva in en fil som inte existerar. OFN_LONGNAMES 0x200000 Visa filnamnen i Win32's långa format istället för i 8.3-format som är standard. OFN_NONETWORKBUTTON 0x20000 Visa inte Nätverks-knappen. OFN_PATHMUSTEXIST 0x800 Path'en måste existera. Återstående medlemmar tas inte upp utan lämnas till er själva att undersöka närmare. De har ingen effekt för det exempel jag just redovisat. ---| Muspekaren i sig själv har ofta en funktionell betydelse i att tala om för en användare vad han kan göra. Pekaren talar ofta om vilken funktion som kan utföras just där. När muspekaren placeras över en Edit-control så ändras pekaren till en textmarkör, när applikationen är upptagen visas ett timglas, när man ska få hjälp om ett föremål visas ett frågetecken, osv. Detta är saker som oftast bara implementeras av standardkontrollerna och bortses ifrån av nya programmerare. För att nu genomföra detta använder vi LoadCursor() och SetCursor(). HCURSOR LoadCursor( HINSTANCE hInstance, LPCTSTR lpCursorName); HCURSOR SetCursor(HCURSOR hcur); Ett exempel vore: HCURSOR hCurse; hCurse = LoadCursor(NULL, IDC_WAIT); SetCursor(hCurse); /* Operation som kommer att ta märkbart med tid */ hCurse = LoadCursor(NULL, IDC_ARROW); SetCursor(hCurse); Självklart kan man också ladda egna pekare som inkluderas som resurser i ens applikation, dessa hämtas sedan med LoadCursor(), eller så kan man hämta en pekare direkt från en fil med LoadCursorFromFile(). Formatet måste vara .ANI eller .CUR. HCURSOR LoadCursorFromFile (LPCTSTR lpFileName); Denna funktion kan också användas för att hämta systemdefinierade pekare. Till exempel, låt oss säga att Win.INI innehåller: [Cursors] Arrow = "arrow.ani" Om vi då exekverar följande: LoadCursorFromFile((LPWSTR)OCR_NORMAL); Så kommer pekaren, återgiven i Arrow.ANI att hämtas. Returnerar NULL om funktionen misslyckas. Övriga noteringar är att pekaren inte ritas om förrens den flyttas, eller ritas om (tas bort och plockas fram igen). ---* Iam Tandem ---# Slarv, buggar & fel Jag redan nu passa på att i förhand be om ursäkt för alla fel, slarv (jag vet att jag slarvar med benämningen klass/struktur) och buggar som tyvärr fått plats i denna text. Men om inte annat får ni känna på den andra halvan av programmering: debugging. ---# Slutord Artikeln har blivit ganska lång, men ändå tagit upp bara det absolut mest grundläggande. Är det någonting som jag missat, eller borde ta upp, så påpeka det, då kan det kanske tas upp i någon framtida text. Som ni förstår är det ett stort område (därav att det finns flertalet böcker om ämnet) och exakt allt kan inte inkluderas. Jag hoppas däremot att jag gett er en tillräckligt inblick för att kunna studera ämnet vidare. Det är inte vidare komplext, och med enkel initiation blir resten desto enklare. Jag skriver gärna mer inom området om intresse finns. Förslag på saker att ta upp plus medium för framtida text skulle också uppskattas. ---# Standard prefixes till variabler b bool c char dw long unsigned integer f 16-bit bitfield (flags) fn Function h Handle l long integer lp long pointer n short integer p pointer pt Long integer holding screen coordinates w Short unsigned integer sz Pointer to null-terminated string (zero) lpsz Long pointer to null-terminated string rgb Long integer holding RGB color values Skriven av: R.G. Gazzaud E-Mail: Gazzaud@operamail.com "Ignorans är inte en ursäkt" - Adept 29 "Ipsa scientia potestas est" - Francis Bacon " Thou what you wilt shall be the whole of the Law" -Liber AL vel Legis I:40 ----------------------------------------------------------------------------- Insändare [] ----------------------------------------------------------------------------- Insändare som inte har blivit kommenterade eller besvarade stannar kvar tills dom blir det, ni får ta och skicka in brev till oss, kan du göra på diox1de@hacksweden.com. --> Netscape 4.05 (Messenger) kryptering Nu är det jag som har en fråga, eftersom det inte är någon än som har skickat in några frågor. Men jag undrar om det är nån som vet någon dokumentation eller c-script som har med algoritmen som krypterar Netscape Messenger i Netscape Communicator 4.05. Jag har märkt att om du väljer att Messenger ska komma ihåg lösenordet till din mailserver så sparas det i en fil /users/username/prefs.js. Kolla raden nedan hur du nu hittar det krypterade lösenordet. user_pref("mail.pop_password", "krypterat passwd"); user_pref("mail.remember_password", true); Första raden handhåller det krypterade lösenordet och den andra om du valt att composer ska komma ihåg ditt lösenord till ditt konto på mailservern. Första raden finns alltså inte om du inte har satt andra raden till "true" diox1de@hacksweden.com --> CuteFTP 3.0.2 krypterings metoder När jag letade upp var de krypterade lösenordet i Netscape Messenger fanns så tänkte jag passa på att kolla det i CuteFTP, eftersom mina kunskaper är begränsade så kan jag inte knäcka dem, därför skickar jag in dom som insändare och se om det är några seriösa som har teorier eller tips osv. Jag fann de krypterade lösenordet i filen /CuteFTP/smdata.dat som visserligen va väldigt otydlig men det gick ändå att se ungefär var de krypterade lösenordet befann sig. De såg ut så här: ftp.sunet.se anonymous¥­ˆ1/2櫧¥ Jag vet att "¥­ˆ1/2櫧¥ " som antagligen är de krypterade lösenordet är i klartext "me@u.com". Några som har tillgång till källkoder som dekrypterar krypterade lösenord eller dokumentation som beskriver algoritmen dom andvänder kan maila den genast. Eller om ni har några ideer eller teorier så kan ni maila dem så publicerar jag dem som svar. ----------------------------------------------------------------------------- Copyright [] ----------------------------------------------------------------------------- Självklart får numret spridas var du vill, men detta verkställs på ett villkor: att du inte ändrar NÅGONTING i zinet. ----------------------------------------------------------------------------- kill -9 666 [] ----------------------------------------------------------------------------- Slut på de intressanta, nästa steg nu är alltså att sitta på IRC till nästa nummer kommer. -----BEGIN PGP SIGNATURE----- Version: PGPfreeware 6.0.2i iQA/AwUBN5zSsnRmgGlPBhFaEQLQngCgjAdjJAjiAqYXs9YTnGFjd0/VaXYAnj+Q X3pmKDomoNWBQp8LyYIdwbqm =estT -----END PGP SIGNATURE-----