DefineDosDevice函式控制虛擬驅動器
1、函式簡介
BOOL WINAPI DefineDosDevice(
__in DWORD dwFlags,
__in LPCTSTR lpDeviceName,
__in LPCTSTR lpTargetPath
);
引數:
DWORD dwFlags,該函式的控制標誌,可取下列值:
DDD_EXACT_MATCH_ON_REMOVE ,確保不會刪除未宣告的物件
DDD_NO_BROADCAST_SYSTEM, 設定 WM_SETTINGCHANGE訊息的狀態為不傳送。(預設情況下,該訊息狀態為傳送)
DDD_RAW_TARGET_PATH, 使用lpTargetPath引數
DDD_REMOVE_DEFINITION, 刪除指定裝置宣告;
如果lpTargetPath為NULL或指向空字串,則刪除第一個裝置或堆疊中頂層的裝置;
If this value is not specified, the string pointed to by the lpTargetPath parameter will become the new mapping for this device.
LPCTSTR lpDeviceName,裝置名稱字串不是必須將冒號作為最後一個字元,除非一個驅動器號被定義,重新定義或刪除。在任何情況下,一個反斜杆是不允許的。
LPCTSTR lpTargetPath,指向路徑字串,如果設定DDD_RAW_TARGET_PATH引數,則指向路徑字串
返回值:
如果成功,返回非0值
失敗,則返回0,可通過GetLastError獲得進一步資訊。
備註:
使用SetVolumeMountPoint函式定義一個驅動器號。
使用DeleteVolumeMountPoint函式刪除一個已存在的驅動器號。
在應用層呼叫DefinesDosDevice建立的符號連結,會放在核心物件空間\\Sessions\\X\\DosDevices\\xxxxxxxx\\ 下
2、範例
#include <windows.h>
int main(int argc, char* argv[])
{
printf("DefineDosDevice!\n");
BOOL rs1 =DefineDosDevice(DDD_REMOVE_DEFINITION,"N:",NULL);
printf(" rs= %d\R\N",rs1);
BOOL rs2 =DefineDosDevice(DDD_RAW_TARGET_PATH, "U:","\\GLOBAL??\\D:\\paper");
if (0)
{
rs2 =DefineDosDevice(DDD_REMOVE_DEFINITION,"U:",NULL);
}
printf(" rs= %d\r\n",rs2);
return 0;
}
在NT系統中,每個裝置都有幾個特殊的路徑,在訪問這些裝置時可以當成檔案訪問,這些路徑不區分大小寫。 訪問硬碟最常用的路徑是://./PhysicalDrive+數字,如//./PhysicalDrive0表示第一個物理硬碟。取得該硬碟控制代碼的方法一般用CreateFile(),如 CString hd=////.//PhysicalDrive0; hDevice = CreateFile( hd, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); 開啟成功後就可以用ReadFile等函式進行讀寫操作。 訪問硬碟還可以有其它路徑,如“/Device/Harddisk0”。 如果想訪問分割槽,可以有以下幾種方法: //?/C:表示C盤的路徑,用訪問硬碟的方法可以對它進行訪問。C盤還可以用"/Device/HarddiskVolume1","/Device/Harddisk0/Partition1",//?/Volume{385baaca-8b42-11dc-bb79-0013d324fc7d}/(用GetVolumeNameForVolumeMountPoint()獲得)。 提示:如果想獲得硬碟整體的物理資訊,可以用這個硬碟上任意一個分割槽的控制代碼來代替硬碟控制代碼。 如果發現某些路徑用CreateFile打不開,可以用DefineDosDevice()給它定義一個碟符,這個碟符可以是A:,B:,也可以是特殊符號(如[:,]:)甚至是數字(1:,2:)。對於非字母的的碟符,在我的電腦裡是不可見的,只有程式可以訪問,這種方法常用於訪問隱藏分割槽。 例: DefineDosDevice (DDD_RAW_TARGET_PATH, "[:" "//Device//Harddisk0//Partition1");//分配一個“[:”碟符,該碟符不可見。 …………………………//處理程式碼 bRet = DefineDosDevice ( DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION| DDD_EXACT_MATCH_ON_REMOVE, "[:", "//Device//Harddisk0//Partition1");//用完後刪除這個碟符。
功能需求相當於umount,要求在一秒種內只剩下C盤。不是很複雜,舉手之勞,呵呵!給我C++和搖滾樂,我Show給你看。
#include <windows.h> #include <cstdlib> #include <iostream> #include <vector> #include <string> #include <algorithm>
using namespace std;
struct SaveContext { string strNtPath; string strDosDevice; };
typedef vector<SaveContext> svrVector;
void RestoreDevice(SaveContext &Context);
int main(void) { //讀磁碟配置並排除C盤 DWORD dwDisks=GetLogicalDrives()&0xfffffffb;
svrVector NtDevices; TCHAR chDosDevice[8]={0}; *(WORD*)chDosDevice=':A'; TCHAR chNtPath[MAX_PATH]={0};
for(int Mask=1;Mask;Mask<<=1,chDosDevice[0]++) { if(dwDisks&Mask) { QueryDosDevice(chDosDevice,chNtPath,MAX_PATH); SaveContext Context; Context.strDosDevice=chDosDevice; Context.strNtPath=chNtPath; //先儲存符號名和裝置之間的關係 NtDevices.push_back(Context); cout<<Context.strDosDevice<<"<--->"<<Context.strNtPath<<endl; //除了C:以外其它的碟符正一個一個的不見了 DefineDosDevice(DDD_REMOVE_DEFINITION,Context.strDosDevice.c_str(),NULL); } } //現在開啟"我的電腦"看看 system("pause"); //現在隱藏的碟符又出現了,呵呵 for_each(NtDevices.begin(),NtDevices.end(),RestoreDevice); return 0; }
void RestoreDevice(SaveContext &Context) { DefineDosDevice(DDD_RAW_TARGET_PATH,Context.strDosDevice.c_str(),Context.strNtPath.c_str()); }
在我的機器上輸出下面的結果:
D:<--->/Device/HarddiskVolume2 E:<--->/Device/CdRom0 F:<--->/Device/CdRom1 G:<--->/Device/HarddiskVolume4 H:<--->/Device/HarddiskVolume5 I:<--->/Device/HarddiskVolume6 J:<--->/Device/HarddiskVolume7 Z:<--->/Device/PGPdisks/PGPdiskVolume1 請按任意鍵繼續. . .