Windows下的程序 一

2022-08-30 10:51:12 字數 4567 閱讀 3184

什麼是程序?程序就是乙個正在執行的程式的例項,由兩部分組成:
核心物件。作業系統用核心物件對程序進行管理,核心物件是作業系統儲存程序統計資訊的地方。

位址空間。其中包含所有可執行檔案或dll模組的**和資料,以及一些其他的資料,提供執行緒執行的環境。

程序比較」懶惰「,它不做任何事情,所有的事情都交給執行緒在它的上下文中執行。乙個程序可以擁有多個執行緒,多個執行緒公用乙個程序的上下文環境來執行程序位址空間中所包含的**。

當系統建立乙個程序的時候,會自動為其建立乙個執行緒,稱為」主線程「,然後由這個執行緒再去建立其他的執行緒。 

建立乙個程序用creteprocess()函式來建立,函式如下:

bool

winapi

createprocessw(

__inout_opt lpwstr lpcommandline,

__in_opt lpsecurity_attributes lpprocessattributes,

__in_opt lpsecurity_attributes lpthreadattributes,

__in bool binherithandles,

__in dword dwcreationflags,

__in_opt lpvoid lpenvironment,

__in_opt lpcwstr lpcurrentdirectory,

__in lpstartupinfow lpstartupinfo,

__out lpprocess_information lpprocessinformation

);

引數說明:

指定新程序要使用的可執行檔案的名稱。

要傳給新程序的命令列字串。

程序安全屬性,通常設為null。

執行緒安全屬性,通常設為null。  

是否可繼承,當設為true時,父程序的上下文環境可由子程序繼承。

標識影響程序建立方式的標誌。一般設為0.

指向一塊記憶體,其中包含新程序要使用的環境字串,預設為null,此時子程序將繼承父程序使用的一組環境字串。

允許父程序設定子程序的當前驅動器和目錄。預設為null,此時新程序的工作目錄與生產新程序的應用程式是一樣的。如果不為null,則lpcurrentdirectory必須指向乙個用0為終止符的字串,其中包含所要的工作驅動器和目錄。必須在路徑中指定乙個驅動器號。

指向乙個startupinfo結構或startupinfoex結構,預設為

指向乙個process_information結構,creteprocess()函式在返回前會初始化這個結構的成員。

程序可以通過以下4種方式終止:

讓主線程的入口點函式返回,可以保證以下操作被執行:

當主線程的入口點函式(winmain, wwinmain, main 或 wmain)返回時,會返回到c/c++執行庫啟動**,後者將正確清理程序使用的全部c執行時資源。釋放了c執行時資源之後,再顯式的呼叫exitprocess,

並將入口點函式返回值傳給它,從而終止整個程序。程序中執行的其他任何執行緒都會隨程序一起終止。

void exitprocess(uint fuexitcode);

該函式會終止程序,並將程序的退出**設為fuexitcode。exitprocess沒有返回值,因為這個時候程序已經結束了,在exitprocess之後的**,再也不會執行了。windows platform sdk文件中說:乙個程序在

其所有執行緒結束後才會終止。不過,c/c++執行庫採用乙個不同的策略,即不管程序中是否還有其他執行緒在執行,只要應用程式的主線程從它的入口點函式返回,c/c++執行庫就會呼叫exitprocess來終止程序。但是,

如果入口點函式呼叫的是exitthread,而不是呼叫exitprocess或者入口點函式直接返回,應用程式的主線程將停止執行,但是只要程序只要海油其他執行緒正在執行,程序就不會終止。不管是呼叫exitprocess還是exitthread都不會再返回當前函式呼叫。這樣做在作業系統層面,程序或執行緒的作業系統資源會被正確清理。但是在c/c++執行庫中有的資源可能不會正確被清理。下面是乙個簡單的例子:

1 #include 2 #include 3

4class

cobj

58 ~cobj()9};

1011

cobj g_globalobj;

1213

intmain()

14

執行上述**,輸出結果如下:

cobj constructor

cobj destructor

這段**構造了兩個物件,乙個是全域性物件,乙個是區域性物件,但是由於直接呼叫了exitprocess,造成程序當場死亡,c/c++執行庫沒有任何機會去清理它的堆疊。

呼叫terminatprocess函式也可以終止乙個程序:

bool terminatprocess(handle hprocess, uint fuexitcode)

terminatprocess也是用來終止乙個程序的,但是與上一節中我們提到的exitprocess的區別在於:exitprocess只能終止本程序,而terminatprocess可以由任何執行緒呼叫來終止另外乙個程序或者它自己的程序。hprocess就是我們所要終止的程序的控制代碼,退出**的值就是fuexitcode。一般只有在無法通過其他方法終止乙個程序的時候,才會呼叫terminatprocess函式。被終止的程序不會得到任何被終止的通知便掛掉了,所以它是沒有機會去做清理工作的。不過不用擔心,雖然程序沒有機會去執行自己的清理工作,但是作業系統會在程序終止後進行徹底的清理工作。程序在終止後不會洩露任何東西。

terminatprocess函式是非同步的,在函式返回的時候,系統並不保證程序已經被強制終止。所以為了確定程序是否終止,我們需要呼叫waitforsingleobject函式。

如果乙個程序中所有的執行緒都終止了,作業系統就會認為沒有任何理由再去保持程序的位址空間,所以就會終止整個程序。而程序的退出**會被設為最後乙個終止的那個執行緒的退出**。

當乙個程序終止時,作業系統會做一下操作。

終止程序中遺留的任何執行緒

釋放程序分配的所有使用者物件和gdi物件,關閉所有核心物件,即使核心物件的計數減1。

程序的退出**從still_active變為傳給exitprocess或terminateprocess函式的**。

程序核心物件的狀態變成已觸發狀態。

程序核心物件的使用計數減1。

當乙個程序終止的時候,如果系統中還有另外乙個程序開啟了這個程序的核心物件的控制代碼,那麼程序核心物件的使用計數就不會為0。

3.1.1 getmodulehandle

hmodule winapi

getmodulehandle

( lpcwstr lpmodulename)

lpmodulename是模組的名稱,要傳遞乙個以0為終止符的字串,指定已在主調程序的位址空間中載入的乙個可執行檔案或dll檔案的名稱,即「**.dll」或者「**.exe」。如果系統找到指定的可執行檔案或dll檔名稱,則會返回可執行檔案/dll檔案映像載入到的基位址,即例項控制代碼。如果沒有副檔名,則預設為「dll」。 如果模組名稱通過路徑來指定,則路徑中必須使用"\",而不是"/". 執行時。該函式通過名稱(大小寫不敏感)來檢視呼叫程序已對映的模組,返回符合的模組控制代碼。如果lpmodulename引數設定為null,則直接返回主調程序的可執行檔案的基位址。成功,則返回控制代碼,失敗,返回null。錯誤資訊:getlasterror()

getmodulehandle函式不會增加所指定模組的引用數,不管呼叫該函式幾次,只要呼叫一次freelibrary函式,該模組就從程序中解除安裝了。在多執行緒中,模組控制代碼在不同執行緒中不總是有效的。如:當在乙個執行緒中呼叫了該函式獲取了某一模組的控制代碼,但在使用該控制代碼之前,另乙個執行緒把該控制代碼 free了,並重新獲取了其他模組的控制代碼。這個時候第乙個執行緒再去使用這個控制代碼變數,就不再是之前它打算操作的那個模組了,而是第二個執行緒修改後的模組控制代碼了。

3.1.2 getmodulehandleex

要知道乙個可執行檔案或dll檔案被載入到程序位址空間的什麼位置,可以使用getmodulehandleex函式來返回乙個控制代碼/基位址。

bool winapi getmodulehandleex( dword dwflags,  lpctstr lpmodulename,  hmodule* phmodule);

引數dwflags指定獲取模組控制代碼的標誌:

引數lpmodulename將當前函式的位址作為引數。

3.1.3 __imagebase

__imagebase是乙個鏈結器定義的偽變數,表明可執行檔案被對映到應用程式記憶體中的位置。

下面是使用以上三種方法來獲取當前程序例項控制代碼的例子:

#include #include 

extern"c

"const

image_dos_header __imagebase;

void

dumpmodule()

intmain()

執行結果如下:

Windows下的程序隱藏

9x環境中windows提供了想光的api函式用於隱藏系統程序。但是到了2000以上系統,已經無法真正的做到對於程序的隱藏,除非編寫底層驅動。但是我們可以通過一些變通的辦法來達到隱藏程序的目的,其中乙個就是遠端注入。簡單的說就是先編寫乙個api的dll,然後將這個dll庫注入到乙個系統程序中,作為它...

Windows下的程序通訊

剪貼簿 剪貼簿 clipped board 實質是win32 api中一組用來傳輸資料的函式和訊息,為windows應用程式之間進行資料共享提供了乙個 中介,windows已建立的剪下 複製 貼上的機制為不同應用程式之間共享不同格式資料提供了一條捷徑。當使用者在應用程式中執行剪下或複製操作時,應 用...

windows下程序通訊

1 程序與程序通訊 2 程序通訊方法 2.1 檔案對映 win32 api中共享記憶體 shared memory 實際就是檔案對映的一種特殊情況。程序在建立檔案對映物件時用0xffffffff來代替檔案控制代碼 handle 就表示了對應的檔案對映物件是從作業系統頁面檔案訪問記憶體,其它程序開啟該...