• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 8  文章 - 4  trackbacks - 0
                 摘要:          本人進(jìn)2年來主要在做windbg調(diào)試相關(guān)的工作, 有一些心得和體會(huì). 我會(huì)逐片寫在我blog中,希望對(duì)大家有用.  windbg調(diào)試最重要的是要對(duì)系統(tǒng)的方方面面有比較深入的了解. 只有了解了系統(tǒng)工作原理才能夠順藤摸瓜.  一步步展開線索.   windbg基礎(chǔ)篇...  閱讀全文
            posted @ 2009-08-22 13:47 Only Soft 閱讀(5273) | 評(píng)論 (4)編輯 收藏
            寄存器沒有地址

            也就是寄存器存放著存儲(chǔ)器的地址.

            CPU通過寄存器中存放的存儲(chǔ)器地址來訪問存儲(chǔ)器中的數(shù)據(jù)

            X86系列的處理器中的寄存器較少,所以
            沒有給cpu中的寄存器進(jìn)行編址,而是直接對(duì)這些寄存器進(jìn)行了命名.在訪問寄存器的時(shí)候只要直接使用寄存器名就可以了.


            lea指令舉例:
            lea 取得地址(第二個(gè)參數(shù))后放入到前面的寄存器。
            如:lea edi, ebp  ,就是將ebp里存儲(chǔ)的地址放入edi, 讓edi也只想這個(gè)地址。
            其實(shí)就是edi 指向ebp指向的存儲(chǔ)器地址

            又如: lea edi, [ebp+0cch],   []中代表存儲(chǔ)器地址, 即ebp指向的存儲(chǔ)器地址+0cch偏移。


            再舉一個(gè)例子:
            mov ecx,30h
            mov eax,0CCCCCCCCh
            rep   stos dword ptr es:[edi]
            stos是串存儲(chǔ)指令,他的功能是將eax中的數(shù)據(jù)存入edi寄存器所指向的存儲(chǔ)器地址中。同時(shí),edi會(huì)增加4(字節(jié)數(shù))
            rep是指令重復(fù)執(zhí)行ecx中填寫的次數(shù)
            posted @ 2010-01-22 18:57 Only Soft 閱讀(321) | 評(píng)論 (0)編輯 收藏
            從FS寄存器獲取當(dāng)前線程ID
            int GetThreadId()
            {
             int ithread = 0;
             _asm{
                xor esi , esi
                mov eax, fs:[esi+18h]     
                   mov ecx, [eax+ 20h]
                   mov eax, [eax+ 24h]
                mov dword ptr[ithread], eax
             }
             return ithread;
            }
            從FS寄存器獲取當(dāng)前進(jìn)程ID
            int GetProcessId()
            {
             int iProcess = 0;
             _asm{
                xor esi , esi
                mov eax, fs:[esi+18h]
                   mov ecx, [eax+ 20h]
                   mov eax, [eax+ 24h]
                mov dword ptr[iProcess ], ecx
             }
             return iProcess ;
            }

            原理:
            1.fs:18h 地址指向線程環(huán)境塊_TEB
            打開windbg可以證明:
            0:028> dd fs:18h L1
            0053:00000018  7eeb8000
            0:028> !teb
            TEB at 7eeb8000
                ExceptionList:        1f8ff15c
                StackBase:            1f900000
                StackLimit:           1f8fc000
                SubSystemTib:         00000000
                FiberData:            00001e00
                ArbitraryUserPointer: 00000000
                Self:                 7eeb8000
                EnvironmentPointer:   00000000
                ClientId:             00001a30 . 00001408
                RpcHandle:            00000000
                Tls Storage:          133d2718
                PEB Address:          7efde000
                LastErrorValue:       0
                LastStatusValue:      c0000302
                Count Owned Locks:    0
                HardErrorMode:        0

            2. 在_TEB中找到線程ID和進(jìn)程ID
            0:028> dt ntdll!_TEB
               +0x000 NtTib            : _NT_TIB
               +0x01c EnvironmentPointer : Ptr32 Void
               +0x020 ClientId         : _CLIENT_ID

            0:028> dt ntdll!_CLIENT_ID
               +0x000 UniqueProcess    : Ptr32 Void  >進(jìn)程ID
               +0x004 UniqueThread     : Ptr32 Void  >線程ID

            當(dāng)然從TEB又可以找到_PEB的地址,從_PEB里面可以獲取到更多的信息。暫且擱筆~~
            posted @ 2010-01-20 15:10 Only Soft 閱讀(3513) | 評(píng)論 (0)編輯 收藏
                  在驅(qū)動(dòng)中分配內(nèi)存,通常你的驅(qū)動(dòng)會(huì)向NT VMM請(qǐng)求內(nèi)存,這是你必須決定你的內(nèi)存是可分頁的或者非可分頁的。
                  分配原則:盡量使用可分頁內(nèi)存,但是必須注意高等級(jí)IRQL執(zhí)行不允許page fault。所以不允許采用可分頁內(nèi)存。可以使用PAGED_CODE();宏來檢查。
                  非分頁內(nèi)存在系統(tǒng)中是一個(gè)有限的資源,取決于操作系統(tǒng)和物理內(nèi)存大小. (NT VMM使用一個(gè)私有算法來計(jì)算非分頁大小,這個(gè)算法使用物理內(nèi)存總是作為計(jì)算因子來計(jì)算。)
                 NT提供如下例程來分配內(nèi)存:
                   ExAllocatePool();
                   ExAllocatePoolWithQuota();
                   ExAllocatePoolWithTag();
                    ExAllocatePoolWithQuotaTag
                   調(diào)用以上例程分配內(nèi)存是必須制定內(nèi)存的類型:
                   NonPagedPool
                   PagedPool
                   NonPagedPoolMustSuccessed.
                   ......................

                關(guān)于非分頁內(nèi)存碎片問題:
                 本來初始化的時(shí)候地址都是相鄰的非分頁池會(huì)變成碎片。而且VMM在托大的時(shí)候也不保證地址相鄰。
                如果請(qǐng)求的分配或者釋放小塊內(nèi)存(小于一個(gè)PAGE_SIZE),可能導(dǎo)致物理內(nèi)存碎片化。這回給系統(tǒng)帶來各種各樣的問題,包括降低系統(tǒng)性能和分配內(nèi)存失敗的情況。
                解決辦法使用旁視列表,旁視列表是一個(gè)NT4.0開始提供的一個(gè)內(nèi)存分配方式;具體請(qǐng)參考WDK docment.
                 順便提一下內(nèi)核棧:
                 每個(gè)在NT平臺(tái)的線程有一個(gè)用戶棧在用戶模式執(zhí)行的時(shí)候使用,一個(gè)內(nèi)核棧在內(nèi)核模式執(zhí)行的時(shí)候使用。當(dāng)線程請(qǐng)求系統(tǒng)服務(wù)而切換到內(nèi)核模式的時(shí)候,陷阱機(jī)制會(huì)切換棧。用分配和線程的內(nèi)核空間棧來覆蓋用戶空間棧。
            在NT3.51之前,內(nèi)核棧限制在兩頁的內(nèi)存中。NT4.0開始增加到12KB.必須要謹(jǐn)慎的在棧上使用變量以節(jié)省占空間,防止超過限制而是系統(tǒng)停止。

            posted @ 2009-11-15 23:57 Only Soft 閱讀(891) | 評(píng)論 (0)編輯 收藏
            首先是參數(shù)說明宏。參數(shù)說明宏一般都是空宏,最常見的是IN和OUT。其實(shí)定義很簡(jiǎn)單,如下所示:
            #define IN
            #define OUT
                    這樣一來,IN和OUT就被定義成了空。無論出現(xiàn)在代碼中的任何地方,對(duì)代碼都不會(huì)有什么實(shí)質(zhì)的影響。在WDK的代碼中,用來作為函數(shù)的說明。IN表示這個(gè)參數(shù)用于輸入;OUT表示這個(gè)參數(shù)用來返回結(jié)果。比如下面的例子:
            NTSTATUS
              ZwQueryInformationFile(
                IN HANDLE  FileHandle,
                OUT PIO_STATUS_BLOCK  IoStatusBlock,
                OUT PVOID  FileInformation,
                IN ULONG  Length,
                IN FILE_INFORMATION_CLASS  FileInformationClass
                );
                    IN和OUT是比較傳統(tǒng)的參數(shù)說明宏。在WDK中到處可見更復(fù)雜的參數(shù)說明宏,比如下面的例子:
            VOID
            NdisProtStatus(
                IN NDIS_HANDLE                          ProtocolBindingContext,
                IN NDIS_STATUS                          GeneralStatus,
                __in_bcount(StatusBufferSize) IN PVOID  StatusBuffer,
                IN UINT                                 StatusBufferSize
                )

                    其中的__in_bcount不但說明參數(shù)StatusBuffer是一個(gè)輸入?yún)?shù),而且說明了StatusBuffer作為一個(gè)緩沖區(qū),它的字節(jié)長(zhǎng)度被另一個(gè)參數(shù)StatusBufferSize所指定。讀者再見到類似的說明宏,就以字面意思理解即可。

                    然后是指定函數(shù)位置的預(yù)編譯指令。比如下面的例子:
            NTSTATUS
            ZwQueryInformationFile(
                IN HANDLE  FileHandle,
                OUT PIO_STATUS_BLOCK  IoStatusBlock,
                OUT PVOID  FileInformation,
                IN ULONG  Length,
                IN FILE_INFORMATION_CLASS  FileInformationClass
                );
                    IN和OUT是比較傳統(tǒng)的參數(shù)說明宏。在WDK中到處可見更復(fù)雜的參數(shù)說明宏,比如下面的例子:
            VOID
            NdisProtStatus(
                IN NDIS_HANDLE                          ProtocolBindingContext,
                IN NDIS_STATUS                          GeneralStatus,
                __in_bcount(StatusBufferSize) IN PVOID  StatusBuffer,
                IN UINT                                 StatusBufferSize
                )
                     其中的__in_bcount不但說明參數(shù)StatusBuffer是一個(gè)輸入?yún)?shù),而且說明了StatusBuffer作為一個(gè)緩沖區(qū),它的字節(jié)長(zhǎng)度被另一個(gè)參數(shù)StatusBufferSize所指定。讀者再見到類似的說明宏,就以字面意思理解即可。

                    然后是指定函數(shù)位置的預(yù)編譯指令。比如下面的例子:
            #pragma alloc_text(INIT, DriverEntry)
            #pragma alloc_text(PAGE, NdisProtUnload)
            #pragma alloc_text(PAGE, NdisProtOpen)
            #pragma alloc_text(PAGE, NdisProtClose)
            #pragma alloc_text

                    這個(gè)宏僅僅用來指定某個(gè)函數(shù)的可執(zhí)行代碼在編譯出來后在sys文件中的位置。內(nèi)核模塊編譯出來之后是一個(gè)PE格式的sys文件,這個(gè)文件的代碼段(text段)中有不同的節(jié)(Section),不同的節(jié)被加載到內(nèi)存中之后處理情況不同。讀者需要關(guān)心的主要是3種節(jié):INIT節(jié)的特點(diǎn)是在初始化完畢之后就被釋放。也就是說,就不再占用內(nèi)存空間了。PAGE節(jié)的特點(diǎn)是位于可以進(jìn)行分頁交換的內(nèi)存空間,這些空間在內(nèi)存緊張時(shí)可以被交換到硬盤上以節(jié)省內(nèi)存。如果未用上述的預(yù)編譯指令處理,則代碼默認(rèn)位于PAGELK節(jié),加載后位于不可分頁交換的內(nèi)存空間中。

                    函數(shù)DriverEntry顯然只需要在初始化階段執(zhí)行一次,因此這個(gè)函數(shù)一般都用#pragma alloc_text(INIT, DriverEntry)使之位于初始化后立刻釋放的空間內(nèi)。為了節(jié)約內(nèi)存,可以把很多函數(shù)放在PAGE節(jié)中。但是要注意:放在PAGE節(jié)中的函數(shù)不可以在Dispatch級(jí)調(diào)用,因?yàn)檫@種函數(shù)的調(diào)用可能誘發(fā)缺頁中斷。但是缺頁中斷處理不能在Dispatch級(jí)完成。為此,一般都用一個(gè)宏P(guān)AGED_CODE()進(jìn)行測(cè)試。如果發(fā)現(xiàn)當(dāng)前中斷級(jí)為Dispatch級(jí),則程序直接報(bào)異常,讓程序員及早發(fā)現(xiàn)。示例如下:
            #pragma alloc_text(PAGE, SfAttachToMountedDevice)
            ……
            NTSTATUS
            SfAttachToMountedDevice (
                IN PDEVICE_OBJECT DeviceObject,
                IN PDEVICE_OBJECT SFilterDeviceObject
                )
            {       
                PSFILTER_DEVICE_EXTENSION newDevExt =
               SFilterDeviceObject->DeviceExtension;
                NTSTATUS status;
                ULONG i;

                PAGED_CODE();
             …

            本文摘自《寒江獨(dú)釣:Windows內(nèi)核安全編程》

            posted @ 2009-11-15 23:03 Only Soft 閱讀(706) | 評(píng)論 (0)編輯 收藏
            User32.dll,kernel32.dll,shell32.dll,gdi32.dll,rpcrt4.dll,comctl32.dll,advapi32.dll,version.dll等dll代表了Win32 API的基本提供者;
            Win32 API中的所有調(diào)用最終都轉(zhuǎn)向了ntdll.dll,再由它轉(zhuǎn)發(fā)至ntoskrnl.exe。ntdll.dll是本機(jī) API用戶模式的終端。真正的接口在ntoskrnl.exe里完成。事實(shí)上,內(nèi)核模式的驅(qū)動(dòng)大部分時(shí)間調(diào)用這個(gè)模塊,如果它們請(qǐng)求系統(tǒng)服務(wù)。Ntdll.dll的主要作用就是讓內(nèi)核函數(shù)的特定子集可以被用戶模式下運(yùn)行的程序調(diào)用。Ntdll.dll通過軟件中斷int 2Eh進(jìn)入ntoskrnl.exe,就是通過中斷門切換CPU特權(quán)級(jí)。
            Ntdll.dll 上面的相關(guān)API函數(shù)原型和參數(shù)都沒有文檔化(Undocumented ):  http://undocumented.ntinternals.net/ 這里提供了Ntdll.dll部分未公開函數(shù)的原型.

            理解window API及函數(shù)原型對(duì)我們的調(diào)試將是非常重要的: 因?yàn)槟銜r(shí)常需要去察看一些函數(shù)的參數(shù),或者根據(jù)參數(shù)找到某些輸入指針.

            例如:
              17  Id: a84.cc4 Suspend: 1 Teb: 7ff3a000 Unfrozen
            ChildEBP RetAddr  Args to Child             
            187ffdb8 77845e6c 7782fc72 00001938 00000000 ntdll!KiFastSystemCallRet
            187ffdbc 7782fc72 00001938 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
            187ffe20 7782fb56 00000000 00000000 00000000 ntdll!RtlpWaitOnCriticalSection+0x13e
            187ffe48 01b05d13 0x77c8ba60 81fa55ed 028766c8 ntdll!RtlEnterCriticalSection+0x150

            從堆棧可以看出線程17 正在進(jìn)入某一個(gè)臨界區(qū).  0x77c8ba60 就是傳入的臨界值 參數(shù).

            17> !cs 0x77c8ba60             --> !cs 是用來查看臨界區(qū)信息的命令
            DebugInfo          = 0x77fbde20
            Critical section   = 0x77c8ba60 (GDI32!semColorSpaceCache+0x0)
            LOCKED
            LockCount          = 0x0
            OwningThread       = 0x00000dd8
            RecursionCount     = 0x1
            LockSemaphore      = 0x0
            SpinCount          = 0x00000000

            可以看到 LOCKED 代表臨界區(qū)是鎖定狀態(tài). 即被占用.
            OwningThread   即是占用線程.

            臨界區(qū)信息結(jié)構(gòu)定義在ntdll, 可以使用如下指令進(jìn)行察看.
            > dt  ntdll!_RTL_CRITICAL_SECTION
               +0x000 DebugInfo        : Ptr32 _RTL_CRITICAL_SECTION_DEBUG
               +0x004 LockCount        : Int4B
               +0x008 RecursionCount   : Int4B
               +0x00c OwningThread     : Ptr32 Void
               +0x010 LockSemaphore    : Ptr32 Void
               +0x014 SpinCount        : Uint4B

            察看某個(gè)動(dòng)態(tài)庫函數(shù)表的指令:
            x ntdll!*
            x kernal!*

            察看結(jié)構(gòu)體定義:
            dt ntdll!*

            任何動(dòng)態(tài)庫包括window 32的用戶態(tài)dll 和用戶自定義動(dòng)態(tài)庫都是生長(zhǎng)在進(jìn)程內(nèi)存空間上的.
            DLL 沒有自己的"私有"地址空間. 它們總是被影射到應(yīng)用程序的虛擬地址空間,在需要時(shí)才會(huì)被讀取到物理內(nèi)存中.
            在本系列的其它章節(jié)我會(huì)談到虛擬地址空間的內(nèi)容.

            通過指令可以看到ntdll 被映射到77800000 ~ 7793c000的內(nèi)存空間中.
            > x *!
            77800000 7793c000   ntdll      (pdb symbols)          c:\mylocalsymbols\ntdll.pdb\F0164DA71FAF4765B8F3DB4F2D7650EA2\ntdll.pdb

            當(dāng)你的代碼(線程)棧中出現(xiàn)地址范圍在 77800000 ~7793c000 之間的函數(shù)調(diào)用都表示在call NTDLL.dll
            比如:
               7  Id: a84.c34 Suspend: 1 Teb: 7ff3f000 Unfrozen
            ChildEBP RetAddr  Args to Child             
            089bfe8c 77845e6c 75a0179c 00000d98 00000000 ntdll!KiFastSystemCallRet
            089bfe90 75a0179c 00000d98 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
            089bfefc 75c9f003 00000d98 ffffffff 00000000 KERNELBASE!WaitForSingleObjectEx+0x98
            089bff14 75c9efb2 00000d98 ffffffff 00000000 kernel32!WaitForSingleObjectExImplementation+0x75
            089bff28 69434fea 00000d98 ffffffff 0780c178 kernel32!WaitForSingleObject+0x12
            WARNING: Stack unwind information not available. Following frames may be wrong.
            此線程中WARNING: Stack unwind information not available. Following frames may be wrong.表示windbg無法翻譯或者找到對(duì)應(yīng)symbols來顯示code stack. 這種錯(cuò)誤往往是保存dump file時(shí)出現(xiàn)的某種異常信息.window也沒有給出合理的解釋.
            以下是MSDN的原話:
            In some cases, the stack trace function will fail in the debugger. This can be caused by a call to an invalid address that caused the debugger to lose the location of the return address; or you may have come across a stack pointer for which you cannot directly get a stack trace; or there could be some other debugger problem. In any case, being able to manually walk a stack is often valuable.

            這時(shí)候你需要手動(dòng)的進(jìn)行恢復(fù)棧調(diào)用. 如果你了解每個(gè)動(dòng)態(tài)庫的映射地址你就很容易進(jìn)行分析了.

            察看動(dòng)態(tài)庫中每個(gè)函數(shù)映射的地址可以采用如下指令 :
            x ntdll!


            手動(dòng)恢復(fù)棧的大致原理如下:
            1. 列出線程環(huán)境信息
             0:000> !teb

            TEB at 7fffe000

                ExceptionList:        0012ff88

                StackBase:            00130000

                StackLimit:           00126000

                ……….

            2. 打開整個(gè)線程棧.
            0:000>
            dds 00126000 00130000

            3. 察看內(nèi)存中所有可能是函數(shù)返回值.  
            >
            ln address



            posted @ 2009-08-24 11:20 Only Soft 閱讀(3102) | 評(píng)論 (0)編輯 收藏
                 摘要:          本人進(jìn)2年來主要在做windbg調(diào)試相關(guān)的工作, 有一些心得和體會(huì). 我會(huì)逐片寫在我blog中,希望對(duì)大家有用.  windbg調(diào)試最重要的是要對(duì)系統(tǒng)的方方面面有比較深入的了解. 只有了解了系統(tǒng)工作原理才能夠順藤摸瓜.  一步步展開線索.   windbg基礎(chǔ)篇...  閱讀全文
            posted @ 2009-08-22 13:47 Only Soft 閱讀(5273) | 評(píng)論 (4)編輯 收藏
            以下是3D中,經(jīng)常會(huì)碰到的一些紋理或者文件格式。僅供參考~~

            TXT
            Update: 2004-2-24    
               無任何格式的ASCII文本文件。

            X文件
            Update: 2004-2-24    
               復(fù)雜的幾何模型通常是由3D建模軟體創(chuàng)建并保存到文件中,Microsoft Direct3D使用的網(wǎng)格模型都是載入這些文件中的對(duì)象。

            TIFF格式
            Update: 2004-2-23    
               TIFF(Tag Image File Format有標(biāo)簽的圖像文件格式)是Aldus在Mac初期開發(fā)的,目的是使掃描圖像標(biāo)準(zhǔn)化。它是跨越Mac與PC平臺(tái)最廣泛的圖像打印格式。TIFF使用LZW無損壓縮,大大減少了圖像體積。另外,TIFF格式最令人激動(dòng)的功能是可以保存通道,這對(duì)于你處理圖像是非常有好處的。

            JPEG格式
            Update: 2004-2-23    
               JPEG(由Joint Photographic Experts Group“聯(lián)合圖形專家組”命名)是我們平時(shí)最常用的圖像格式。它是一個(gè)最有效、最基本的有損壓縮格式,被極大多數(shù)的圖形處理軟件所支持。JPEG格式的圖像還廣泛用于Web的制作。如果對(duì)圖像質(zhì)量要求不高,但又要求存儲(chǔ)大量圖片,使用JPEG無疑是一個(gè)好辦法。

            Amiga IFF格式
            Update: 2004-2-23    
               Amiga是由Commodore開發(fā)的,由于該公司已退出計(jì)算機(jī)市場(chǎng),因此,Amiga IFF格式也將漸漸地被廢棄。

            PCX格式
            Update: 2004-2-23    
               PCX是DOS下的古老程序PC PaintBrush固有格式的擴(kuò)展名,因此這個(gè)格式已不受歡迎。

            TGA格式
            Update: 2004-2-23    
               TrueVision的TGA(Targa)和NuVista視頻板可將圖像和動(dòng)畫轉(zhuǎn)入電視中,PC機(jī)上的視頻應(yīng)用軟件都廣泛支持TGA格式。

            Scitex CT格式
            Update: 2004-2-23    
               Scitex CT格式支持灰度級(jí)圖像、RGB圖像、CMYK圖像。Photoshop可以打開諸如Scitex圖像處理設(shè)備的數(shù)字化圖像。

            PDF格式
            Update: 2004-2-23    
               PDF(Portable Document Format)是由Adobe Systems創(chuàng)建的一種文件格式,允許在屏幕上查看電子文檔。PDF文件還可被嵌入到Web的HTML文檔中。

            PICT格式
            Update: 2004-2-23    
               PICT是Mac上常見的數(shù)據(jù)文件格式之一。如果你要將圖像保存成一種能夠在Mac上打開的格式,選擇PICT格式要比JPEG要好,因?yàn)樗蜷_的速度相當(dāng)快。另外,你如果要在PC機(jī)上用Photoshop打開一幅Mac上的PICT文件,建議你在PC機(jī)上安裝QuickTime,否則,將不能打開PICT圖像。

            BMP格式
            Update: 2004-2-23    
               BMP(Windows Bitmap)是微軟開發(fā)的Microsoft Pain的固有格式,這種格式被大多數(shù)軟件所支持。BMP格式采用了一種叫RLE的無損壓縮方式,對(duì)圖像質(zhì)量不會(huì)產(chǎn)生什么影響。

            PNG格式
            Update: 2004-2-23    
               PNG是專門為Web創(chuàng)造的。PNG格式是一種將圖像壓縮到Web上的文件格式,和GIF格式不同的是,PNG格式并不僅限于256色。

            GIF格式
            Update: 2004-2-23    
               GIF是輸出圖像到網(wǎng)頁最常采用的格式。GIF采用LZW壓縮,限定在256色以內(nèi)的色彩。GIF格式以87a和89a兩種代碼表示。GIF87a嚴(yán)格支持不透明像素。而GIF89a可以控制那些區(qū)域透明,因此,更大地縮小了GIF的尺寸。

            后面的文章將會(huì)對(duì)Gif格式做一個(gè)實(shí)現(xiàn)。請(qǐng)期待

            posted @ 2009-04-04 01:07 Only Soft 閱讀(573) | 評(píng)論 (0)編輯 收藏

            本程序只關(guān)注對(duì)Gif紋理的實(shí)現(xiàn)。不對(duì)GIF加解密進(jìn)行詳細(xì)的說明。
            GIF文檔解析采用gif89a.h, gif89a.cpp實(shí)現(xiàn)。

            gif89a 代碼下載

            詳細(xì)紋理生成代碼:


            bool Cmenu::CreateTextureFromGif()
            {
                HRESULT hr;
              CGif89a
            * pGif    = new CGif89a();
                BOOL bopen 
            = pGif->open("110743081.gif",true);
                
                
            int index = 0;
                LPCFRAME pFrame    
            = pGif->getFrame(index);
                
            if (!pFrame)
                    
            return false;


                BYTE
            * pColorTable    = pGif->getColorTable(index);
                
            if (!pColorTable)
                    
            return false;

                
            //create empty Texture.
                hr = D3DXCreateTexture(m_pDevice,pFrame->imageWidth,pFrame->imageHeight,0,0,D3DFMT_X8B8G8R8,D3DPOOL_MANAGED,&m_pTexture[0]);
                
            if(FAILED(hr))
                    
            return false;

                D3DSURFACE_DESC textureDesc;
                m_pTexture[
            0]->GetLevelDesc(0,&textureDesc);

                
            if(textureDesc.Format != D3DFMT_X8B8G8R8)
                    
            return false;

                D3DLOCKED_RECT locketrect;
                hr 
            = m_pTexture[0]->LockRect( 0,&locketrect,0,0 );
                
            if(FAILED(hr))
                    
            return false;

                BYTE
            * pBytes = (BYTE*)locketrect.pBits;
                DWORD lPitch 
            = locketrect.Pitch;

                
            int idx_trs    = pFrame->ctrlExt.trsFlag ? pFrame->ctrlExt.trsColorIndex : -1;

                
            int x=0,y=0;
                
            int    sx, sy;
                
            if(x<0)
                    sx    
            = -x;
                
            else
                    sx    
            = 0;
                
            if(y<0)
                    sy    
            = -y;
                
            else
                    sy    
            = 0;


                DWORD width    
            = pFrame->imageWidth;

                pBytes 
            += lPitch*sy;
                
            for( DWORD h=sy; y+h<pFrame->imageHeight; h++ )
                
            {
                    DWORD
            * pDstData32 = ((DWORD*)pBytes) + sx;
                    WORD
            *  pDstData16 = ((WORD*)pBytes) + sx;
                    BYTE
            * pPixel;

                    BYTE* pIdx    = pFrame->dataBuf + (pFrame->imageWidth*(((y>0)?y:0)+h) + ((x>0)?x:0));

                    
            for( DWORD w=sx; w<width; w++ )
                    
            {
                        pPixel    
            = pColorTable + (*pIdx)*3;
                        
            if (*pIdx==idx_trs)
                        
            {
                            
            //if( 32 == ddsd.ddpfPixelFormat.dwRGBBitCount )
                            
            //    pDstData32[w] = 0;
                            
            //else
                            
            //    pDstData16[w] = 0;
                        }

                        
            else
                        
            {

                            DWORD m_nRShiftL 
            = 0; DWORD m_nRShiftR = 0;
                            DWORD m_nGShiftL 
            = 0; DWORD m_nGShiftR = 0;
                            DWORD m_nBShiftL 
            = 0; DWORD m_nBShiftR = 0;
                            DWORD m_nAShiftL 
            = 0; DWORD  m_nAShiftR = 0;

                            DWORD dr 
            = ((DWORD(pPixel[0])>>(m_nRShiftL))<<m_nRShiftR);
                            DWORD dg = ((DWORD(pPixel[1])>>(m_nGShiftL))<<8);
                            DWORD db = ((DWORD(pPixel[2])>>(m_nBShiftL))<<16);
                            DWORD da = ((0xff>>(m_nAShiftL))<<24);
              
                       pDstData32[w] = (DWORD)(dr+dg+db+da);
             

                        }

                        pIdx 
            ++;
                    }

                    
                    pBytes 
            += lPitch;
                }


                m_pTexture[
            0]->UnlockRect(0);
                
            return true;
            }
            如有任何疑問請(qǐng)留言。交流~~
            posted @ 2009-04-04 01:05 Only Soft 閱讀(830) | 評(píng)論 (0)編輯 收藏
            僅列出標(biāo)題  
            色婷婷狠狠久久综合五月| 人妻无码久久精品| 久久久精品人妻一区二区三区四| 久久99热这里只有精品国产| 精品久久久久久国产潘金莲| 91久久精品电影| 狠狠色婷婷久久综合频道日韩| 久久狠狠高潮亚洲精品| 久久99精品国产麻豆婷婷| 中文字幕久久久久人妻| 麻豆精品久久精品色综合| 色妞色综合久久夜夜| 久久国产精品久久精品国产| 亚洲AⅤ优女AV综合久久久| 亚洲欧美伊人久久综合一区二区| 日本久久久久久中文字幕| 国产精品久久久久久久app| 久久免费精品视频| 久久精品卫校国产小美女| 国产午夜电影久久| 久久九九精品99国产精品| 亚洲国产精品一区二区三区久久 | 99久久亚洲综合精品网站| 久久中文字幕人妻丝袜| 久久精品国产亚洲av瑜伽| 久久精品中文字幕无码绿巨人| 亚洲va久久久久| 色综合久久88色综合天天 | 久久精品国产精品亚洲精品| 亚洲精品乱码久久久久久中文字幕| 久久99精品免费一区二区| 伊人色综合久久天天| 国产91久久综合| 精品久久久久久| 国内精品伊人久久久久| 无遮挡粉嫩小泬久久久久久久| 久久这里有精品| 99久久国产综合精品女同图片| 久久综合色之久久综合| 久久丝袜精品中文字幕| 伊人久久大香线蕉无码麻豆|