1. 程式人生 > >DefineDosDevice函式控制虛擬驅動器

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 請按任意鍵繼續. . .