WDM驱动安装和卸载

编译环境:VS2012 + WIN8 64 

测试环境:VM WIN7

测试对象:WDM驱动 (sys文件 和 inf文件)

项目类型:Win32 Console Application

其它说明:代码来源于网络,经小修改而成,加载驱动方法还有很多(如SetupCopyOEMInf等OEM系列函数),但是逆向EzDriverInstaller驱动加载器,发现和下面代码逻辑基本一致,所以最终记录以下代码,以便日后使用。

代码如下:

[cpp]  view plain copy
  1. // WinInstallWin.cpp :   
  2. //  
  3.   
  4. #include "stdafx.h"  
  5.   
  6. #include <windows.h>  
  7. #include <newdev.h>  
  8. #include <setupapi.h>  
  9. #include <locale.h>  
  10.   
  11. #pragma comment(lib, "newdev.lib")  
  12. #pragma comment(lib, "setupapi.lib")  
  13.   
  14. #ifndef MAX_DEVICE_ID_LEN  
  15. #define MAX_DEVICE_ID_LEN     200  
  16. #define MAX_DEVNODE_ID_LEN    MAX_DEVICE_ID_LEN  
  17. #define MAX_GUID_STRING_LEN   39          // 38 chars + terminator null  
  18. #define MAX_CLASS_NAME_LEN    32  
  19. #endif  
  20.   
  21.   
  22. WORD g_wVender = 0;  
  23. WORD g_wHardware = 0;  
  24. TCHAR g_strVender[20][64] = {0};  
  25. TCHAR g_strHardware[20][64] = {0};  
  26. TCHAR g_strHID[MAX_PATH+1] = {0};  
  27.   
  28. //打印错误  
  29. VOID ShowErrorMsg(DWORD Count,LPCWSTR szData)  
  30. {  
  31.     printf("%d\n%s",&Count,&szData);  
  32. }  
  33.   
  34. //过滤字符  
  35. VOID FindComma(LPSTR szData)  
  36. {  
  37.     WORD wLen = (WORD)strlen(szData);  
  38.     WORD wIdx;  
  39.     WORD wLoop;   
  40.     CHAR szTmp[128] = {0};  
  41.   
  42.     for (wIdx = 0, wLoop = 0; wLoop < wLen; wLoop++)  
  43.     {  
  44.         if (szData[wLoop] == ',')  
  45.             szData[wLoop] = '.';  
  46.         else if (szData[wLoop] == ' ')  
  47.             continue;  
  48.         szTmp[wIdx++] = szData[wLoop];  
  49.     }  
  50.     memcpy(szData, szTmp, wIdx*sizeof(char));  
  51.     szData[wIdx] = 0;  
  52. }  
  53.   
  54. //去除字符串左边的空格  
  55. VOID StrLTrim(LPSTR szData)  
  56. {  
  57.     LPSTR ptr = szData;  
  58.     //判断是否为空格  
  59.     while (isspace(*ptr))  
  60.             ptr++;  
  61.   
  62.     if (strcmp(ptr, szData))  
  63.     {  
  64.         WORD wLen = (WORD)(strlen(szData) - (ptr - szData));  
  65.         memmove(szData, ptr, (wLen+1)*sizeof(char));  
  66.     }  
  67. }  
  68.   
  69. //去除字符串右边的空格  
  70. VOID StrRTrim(LPSTR szData)  
  71. {  
  72.     LPSTR ptr  = szData;  
  73.     LPSTR pTmp = NULL;  
  74.   
  75.     //debug模式下 使用isspace判断中文 需要设置编码  
  76.     #if defined(WIN32) && defined(_DEBUG)  
  77.     char* locale = setlocale( LC_ALL, ".OCP" );  
  78.     #endif   
  79.   
  80.     while (*ptr != 0)  
  81.     {  
  82.         //判断是否为空格  
  83.         if (isspace(*ptr))  
  84.         {  
  85.             if (!pTmp)  
  86.                 pTmp = ptr;  
  87.         }  
  88.         else  
  89.             pTmp = NULL;  
  90.         ptr++;  
  91.     }  
  92.   
  93.     if (pTmp)  
  94.     {  
  95.         *pTmp = 0;  
  96.         memmove(szData, szData, strlen(szData) - strlen(pTmp));  
  97.     }  
  98. }  
  99.   
  100. //从字符串右边开始截取字符串  
  101. VOID StrRight(LPSTR szData, WORD wCount)  
  102. {  
  103.     WORD wLen = (WORD)strlen(szData) - wCount;  
  104.   
  105.     if (wCount > 0x7FFF)//负数  
  106.         wCount = 0;  
  107.     if (wCount >= (WORD)strlen(szData))  
  108.         return;  
  109.   
  110.     memmove(szData, szData + wLen, wCount * sizeof(char));  
  111.     szData[wCount] = 0;  
  112. }  
  113.   
  114. VOID ConvertGUIDToString(const GUID guid, LPSTR pData)  
  115. {  
  116.     CHAR szData[30] = {0};  
  117.     CHAR szTmp[3]   = {0};  
  118.     WORD wLoop;  
  119.   
  120.     sprintf_s(pData, _countof(szData), "%04X-%02X-%02X-", guid.Data1, guid.Data2, guid.Data3);  
  121.     for (wLoop = 0; wLoop < 8; wLoop++)  
  122.     {  
  123.         if (wLoop == 2)  
  124.             strcat_s(szData, "-");  
  125.         sprintf_s(szTmp, _countof(szTmp), "%02X", guid.Data4[wLoop]);  
  126.         strcat_s(szData, szTmp);  
  127.     }  
  128.   
  129.     memcpy(pData + strlen(pData), szData, strlen(szData));  
  130. }  
  131.   
  132. BOOL AnsiToUnicode(LPCSTR Source, const WORD sLen, LPWSTR Destination, const WORD wLen)  
  133. {  
  134.     return MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, Source, sLen, Destination, wLen);  
  135. }  
  136.   
  137. BOOL UnicodeToAnsi(LPCWSTR Source, const WORD wLen, LPSTR Destination, const WORD sLen)  
  138. {  
  139.     return WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, Source, wLen, Destination, sLen, 0L, 0L);  
  140. }  
  141.   
  142. // 初始化全局变量  
  143. __inline VOID InitialGlobalVar()  
  144. {  
  145.     WORD wLoop;  
  146.   
  147.     g_wVender = g_wHardware = 0;  
  148.     for (wLoop = 0; wLoop < 20; wLoop++)  
  149.     {  
  150.         RtlZeroMemory(g_strVender[wLoop], sizeof(TCHAR)*64);  
  151.         RtlZeroMemory(g_strHardware[wLoop], sizeof(TCHAR)*64);  
  152.     }  
  153. }  
  154.   
  155. //安装驱动功能  
  156. __inline BOOL IsInstalled()  
  157. {  
  158.     HDEVINFO hDevInfo = 0L;  
  159.     SP_DEVINFO_DATA spDevInfoData = {0L};  
  160.     WORD wIdx;  
  161.     BOOL bIsFound;  
  162.   
  163.     //得到设备信息结构的句柄  
  164.     hDevInfo = SetupDiGetClassDevs(0L, 0, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT);  
  165.     if (hDevInfo == INVALID_HANDLE_VALUE)  
  166.     {  
  167.         ShowErrorMsg(GetLastError(), _T("SetupDiGetClassDevs"));  
  168.         return FALSE;  
  169.     }  
  170.   
  171.     spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);  
  172.     wIdx = 0;  
  173.     bIsFound = 0;  
  174.     while (++wIdx)  
  175.     {  
  176.         //找到所有的硬件设备,并且可以得到所有的硬件设备的详细信息  
  177.         if (SetupDiEnumDeviceInfo(hDevInfo, wIdx, &spDevInfoData))  
  178.         {  
  179.             LPTSTR ptr;  
  180.             LPBYTE pBuffer = NULL;  
  181.             DWORD dwData  = 0L;  
  182.             DWORD dwRetVal;  
  183.             DWORD dwBufSize = 0L;  
  184.   
  185.             while (TRUE)  
  186.             {  
  187.                 //可以在前面得到的指向某一个具体设备信息集合的指针中取出某一项信息  
  188.                 dwRetVal = SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_HARDWAREID,  
  189.                     &dwData, (PBYTE)pBuffer, dwBufSize, &dwBufSize);  
  190.                 if (!dwRetVal)  
  191.                     dwRetVal = GetLastError();  
  192.                 else  
  193.                     break;  
  194.                 if (dwRetVal == ERROR_INVALID_DATA)  
  195.                     break;  
  196.                 else if (dwRetVal == ERROR_INSUFFICIENT_BUFFER)  
  197.                 {  
  198.                     if (pBuffer)  
  199.                         LocalFree(pBuffer);  
  200.                     pBuffer = (LPBYTE)LocalAlloc(LPTR, dwBufSize);  
  201.                 }  
  202.                 else  
  203.                 {  
  204.                     ShowErrorMsg(dwRetVal, _T("SetupDiGetDeviceRegistryProperty"));  
  205.                     //销毁一个设备信息集合  
  206.                     SetupDiDestroyDeviceInfoList(hDevInfo);  
  207.                     return FALSE;  
  208.                 }  
  209.             }  
  210.   
  211.             if (dwRetVal == ERROR_INVALID_DATA)   
  212.                 continue;  
  213.   
  214.             for (ptr = (LPTSTR)pBuffer; *ptr && (ptr < (LPTSTR)&pBuffer[dwBufSize]); ptr += _tcslen(ptr) + sizeof(TCHAR))  
  215.             {  
  216.                 WORD wLoop;  
  217.   
  218.                 for (wLoop = 0; wLoop < g_wHardware; wLoop++)  
  219.                 {  
  220.                     if (!_tcscmp(g_strHardware[wLoop], ptr))  
  221.                     {  
  222.                         bIsFound = TRUE;  
  223.                         break;  
  224.                     }  
  225.                 }  
  226.             }  
  227.             if (pBuffer)  
  228.                 LocalFree(pBuffer);  
  229.             if (bIsFound)  
  230.                 break;  
  231.         }  
  232.     }  
  233.     //销毁一个设备信息集合  
  234.     SetupDiDestroyDeviceInfoList(hDevInfo);  
  235.     return bIsFound;  
  236. }  
  237.   
  238. //寻找指定的节名 如果找到返回TRUE 反之返回FALSE  
  239. BOOL FindSectionName(FILE *pFile, const char *szKey)  
  240. {  
  241.     char szData[256] = {0};  
  242.   
  243.     if (!pFile)  
  244.         return FALSE;  
  245.   
  246.     //将文件内部的位置指针重新指向一个流(数据流/文件)的开头  
  247.     rewind(pFile);  
  248.     //循环读取文件内容  
  249.     while (!feof(pFile))  
  250.     {  
  251.         //读取一行  
  252.         fgets(szData, 255, pFile);  
  253.         //去除前后空格  
  254.         StrLTrim(szData);  
  255.         StrRTrim(szData);  
  256.   
  257.         if (strcmp(szKey, szData) == 0)  
  258.             return TRUE;          
  259.     }  
  260.     return FALSE;  
  261. }  
  262.   
  263. //得到INF文件中节的数量  
  264. __inline BOOL GetSectionData(FILE* pFile, const char* szKey, const char bIsVender)  
  265. {  
  266.     char szData[128] = {0};  
  267.       
  268.     if (bIsVender)  
  269.         strcpy_s(szData, szKey);  
  270.     else  
  271.         sprintf_s(szData, _countof(szData), "[%s]", szKey);  
  272.   
  273.     if (FindSectionName(pFile, szData) == FALSE)  
  274.         return FALSE;  
  275.   
  276.     RtlZeroMemory(szData, sizeof(char)*128);  
  277.     while (!feof(pFile))  
  278.     {  
  279.         char *str = NULL;  
  280.         fgets(szData, 127, pFile);  
  281.         szData[strlen(szData)-1] = 0;  
  282.         StrLTrim(szData);  
  283.         StrRTrim(szData);  
  284.         if (!*szData)  
  285.             continue;  
  286.         if (szData[0] == ';')  
  287.             continue;  
  288.   
  289.         if (strchr(szData, '['))  
  290.         {  
  291.             StrLTrim(szData);  
  292.             if (szData[0] != ';')  
  293.                 return 1;  
  294.             else  
  295.                 continue;  
  296.         }  
  297.   
  298.         if (bIsVender)  
  299.             str = strchr(szData, '=');  
  300.         else  
  301.             str = strchr(szData, ',');  
  302.   
  303.         if (*str)  
  304.         {  
  305.             char szTmp[128] = {0};  
  306.             WORD pos = (WORD)(str - szData + 1);  
  307.   
  308.             StrRight(szData, (short)(strlen(szData)-pos));  
  309.             StrLTrim(szData);  
  310.             StrRTrim(szData);  
  311.             FindComma(szData);  
  312.             if (bIsVender)  
  313.             {  
  314.                 AnsiToUnicode(szData, strlen(szData), g_strVender[g_wVender++], 64);  
  315.             }  
  316.             else  
  317.             {  
  318.                 AnsiToUnicode(szData, strlen(szData), g_strHardware[g_wHardware++], 64);  
  319.             }  
  320.         }/* end if */  
  321.     }  
  322.     return TRUE;  
  323. }  
  324.   
  325. //得到INF文件相关数据  
  326. BOOL GetINFData(FILE *pFile)  
  327. {  
  328.     WORD wLoop;  
  329.   
  330.     if (!g_wVender || !g_wHardware)  
  331.         InitialGlobalVar();  
  332.     if (GetSectionData(pFile, "[Manufacturer]", TRUE) == FALSE)  
  333.         return 0;  
  334.                                  
  335.     for (wLoop = 0; wLoop < g_wVender; wLoop++)  
  336.     {  
  337.         CHAR szVender[64] = {0};  
  338.         UnicodeToAnsi(g_strVender[wLoop], _tcslen(g_strVender[wLoop]), szVender, 64);  
  339.         GetSectionData(pFile, szVender, FALSE);  
  340.     }  
  341.     if (g_wHardware != 0)  
  342.     {  
  343.         if (IsInstalled() == TRUE)//如果已经安装  
  344.             return FALSE;  
  345.         else  
  346.             return TRUE;  
  347.     }  
  348.     return FALSE;  
  349. }  
  350.   
  351. //实质性的安装驱动  
  352. __inline BOOL InstallClassDriver(LPCTSTR theINFName)  
  353. {  
  354.     GUID guid = {0};  
  355.     SP_DEVINFO_DATA spDevData = {0};  
  356.     HDEVINFO hDevInfo = 0L;  
  357.     TCHAR className[MAX_CLASS_NAME_LEN] = {0};  
  358.     LPTSTR pHID = NULL;  
  359.     WORD wLoop;  
  360.     BOOL bRebootRequired;  
  361.   
  362.     //取得此驱动的GUID值  
  363.     if (!SetupDiGetINFClass(theINFName, &guid, className, MAX_CLASS_NAME_LEN, 0))  
  364.     {  
  365.         ShowErrorMsg(GetLastError(), _T("SetupDiGetINFClass"));  
  366.         return FALSE;  
  367.     }  
  368.   
  369.     //创建设备信息块列表  
  370.     hDevInfo = SetupDiCreateDeviceInfoList(&guid, 0);  
  371.     if (hDevInfo == INVALID_HANDLE_VALUE)  
  372.     {  
  373.         ShowErrorMsg(GetLastError(), _T("SetupDiCreateDeviceInfoList"));  
  374.         return FALSE;  
  375.     }  
  376.   
  377.     spDevData.cbSize = sizeof(SP_DEVINFO_DATA);  
  378.     //创建设备信息块  
  379.     if (!SetupDiCreateDeviceInfo(hDevInfo, className, &guid, 0L, 0L, DICD_GENERATE_ID, &spDevData))  
  380.     {  
  381.         ShowErrorMsg(GetLastError(), _T("SetupDiCreateDeviceInfo"));  
  382.         //销毁一个设备信息集合  
  383.         SetupDiDestroyDeviceInfoList(hDevInfo);  
  384.         return FALSE;  
  385.     }  
  386.   
  387.     for (wLoop = 0; wLoop < g_wHardware; wLoop++)  
  388.     {  
  389.         if (pHID)  
  390.             LocalFree(pHID);  
  391.   
  392.         pHID = (LPTSTR)LocalAlloc(LPTR, _tcslen(g_strHardware[wLoop])*2*sizeof(TCHAR));  
  393.         if (!pHID)  
  394.         {  
  395.             ShowErrorMsg(GetLastError(), _T("LocalAlloc"));  
  396.             //销毁一个设备信息集合  
  397.             SetupDiDestroyDeviceInfoList(hDevInfo);  
  398.             return FALSE;  
  399.         }  
  400.   
  401.         _tcscpy_s(pHID, _tcslen(g_strHardware[wLoop])*2, g_strHardware[wLoop]);  
  402.         //设定硬件ID  
  403.         if (!SetupDiSetDeviceRegistryProperty(hDevInfo, &spDevData, SPDRP_HARDWAREID, (PBYTE)pHID,  
  404.             (DWORD)(_tcslen(g_strHardware[wLoop])*2*sizeof(TCHAR))))  
  405.         {  
  406.             ShowErrorMsg(GetLastError(), _T("SetupDiSetDeviceRegistryProperty"));  
  407.             //销毁一个设备信息集合  
  408.             SetupDiDestroyDeviceInfoList(hDevInfo);  
  409.             LocalFree(pHID);  
  410.             return FALSE;  
  411.         }  
  412.         //调用相应的类程序来注册设备  
  413.         if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, hDevInfo, &spDevData))  
  414.         {  
  415.             ShowErrorMsg(GetLastError(), _T("SetupDiCallClassInstaller"));  
  416.             //销毁一个设备信息集合  
  417.             SetupDiDestroyDeviceInfoList(hDevInfo);  
  418.             LocalFree(pHID);  
  419.             return FALSE;  
  420.         }  
  421.   
  422.         bRebootRequired = FALSE;  
  423.         //安装更新和硬件ID相匹配的驱动程序  
  424.         if (!UpdateDriverForPlugAndPlayDevices(0L, g_strHardware[wLoop], theINFName,   
  425.             INSTALLFLAG_FORCE, &bRebootRequired))  
  426.         {  
  427.             DWORD dwErrorCode = GetLastError();  
  428.             //调用相应的类程序来移除设备  
  429.             if (!SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, &spDevData))  
  430.                 ShowErrorMsg(GetLastError(), _T("SetupDiCallClassInstaller(Remove)"));  
  431.             ShowErrorMsg((WORD)dwErrorCode, _T("UpdateDriverForPlugAndPlayDevices"));  
  432.             //销毁一个设备信息集合  
  433.             SetupDiDestroyDeviceInfoList(hDevInfo);  
  434.             LocalFree(pHID);  
  435.             return FALSE;  
  436.         }  
  437.         LocalFree(pHID);  
  438.         pHID = NULL;  
  439.     }  
  440.     //销毁一个设备信息集合  
  441.     SetupDiDestroyDeviceInfoList(hDevInfo);  
  442.     _tprintf(_T("Install Successed\n"));  
  443.     return TRUE;  
  444. }  
  445.   
  446. // 安装WDM驱动的测试工作  
  447. BOOL StartInstallWDMDriver(LPCTSTR theInfName)  
  448. {  
  449.     HDEVINFO hDevInfo = 0L;  
  450.     GUID guid = {0L};  
  451.     SP_DEVINSTALL_PARAMS spDevInst = {0L};  
  452.     TCHAR strClass[MAX_CLASS_NAME_LEN] = {0L};  
  453.   
  454.     //取得此驱动的GUID值  
  455.     if (!SetupDiGetINFClass(theInfName, &guid, strClass, MAX_CLASS_NAME_LEN, 0))  
  456.     {  
  457.         ShowErrorMsg(GetLastError(), _T("SetupDiGetINFClass"));  
  458.         return FALSE;  
  459.     }  
  460.   
  461.     //得到设备信息结构的句柄  
  462.     hDevInfo = SetupDiGetClassDevs(&guid, 0L, 0L, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_PROFILE);  
  463.     if (!hDevInfo)  
  464.     {  
  465.         ShowErrorMsg(GetLastError(), _T("SetupDiGetClassDevs"));  
  466.         return FALSE;  
  467.     }  
  468.   
  469.       
  470.     spDevInst.cbSize = sizeof(SP_DEVINSTALL_PARAMS);  
  471.     //获得指定设备的安装信息  
  472.     if (!SetupDiGetDeviceInstallParams(hDevInfo, 0L, &spDevInst))  
  473.     {  
  474.         ShowErrorMsg(GetLastError(), _T("SetupDiGetDeviceInstallParams"));  
  475.         return FALSE;  
  476.     }  
  477.   
  478.     spDevInst.Flags   = DI_ENUMSINGLEINF;  
  479.     spDevInst.FlagsEx = DI_FLAGSEX_ALLOWEXCLUDEDDRVS;  
  480.     _tcscpy_s(spDevInst.DriverPath, _countof(spDevInst.DriverPath), theInfName);  
  481.   
  482.     //为设备信息集或者是一个实际的设备信息单元设置或清除类安装参数  
  483.     if (!SetupDiSetDeviceInstallParams(hDevInfo, 0, &spDevInst))  
  484.     {  
  485.         ShowErrorMsg(GetLastError(), _T("SetupDiSetDeviceInstallParams"));  
  486.         return FALSE;  
  487.     }  
  488.   
  489.     //获取这个设备的驱动程序信息列表  
  490.     if (!SetupDiBuildDriverInfoList(hDevInfo, 0, SPDIT_CLASSDRIVER))  
  491.     {  
  492.         ShowErrorMsg(GetLastError(), _T("SetupDiDeviceInstallParams"));  
  493.         return FALSE;  
  494.     }  
  495.   
  496.     //销毁一个设备信息集合  
  497.     SetupDiDestroyDeviceInfoList(hDevInfo);  
  498.   
  499.     //进入安装设备驱动函数  
  500.     return InstallClassDriver(theInfName);  
  501. }  
  502.   
  503. // 卸载WDM驱动  
  504. VOID UninstallWDMDriver(LPCTSTR theHardware)  
  505. {  
  506.     SP_DEVINFO_DATA spDevInfoData = {0};  
  507.     HDEVINFO hDevInfo = 0L;  
  508.     WORD wIdx, wCount = 0;  
  509.   
  510.     //得到设备信息结构的句柄  
  511.     hDevInfo = SetupDiGetClassDevs(0L, 0L, 0L, DIGCF_ALLCLASSES | DIGCF_PRESENT);  
  512.     if (hDevInfo == INVALID_HANDLE_VALUE)  
  513.     {  
  514.         ShowErrorMsg(GetLastError(), _T("SetupDiGetClassDevs"));  
  515.         return;  
  516.     }  
  517.   
  518.     wIdx = 0;  
  519.     while (TRUE)  
  520.     {  
  521.         spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);  
  522.         //找到所有的硬件设备,并且可以得到所有的硬件设备的详细信息  
  523.         if (SetupDiEnumDeviceInfo(hDevInfo, wIdx, &spDevInfoData))  
  524.         {  
  525.             char Buffer[2048] = {0};  
  526.   
  527.             //可以在前面得到的指向某一个具体设备信息集合的指针中取出某一项信息  
  528.             if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_HARDWAREID,  
  529.                 0L, (PBYTE)Buffer, 2048, 0L))  
  530.             {  
  531.                 if (!_tcscmp(theHardware, (LPTSTR)Buffer))  
  532.                 {  
  533.                     //从系统中删除一个注册的设备接口  
  534.                     if (!SetupDiRemoveDevice(hDevInfo, &spDevInfoData))  
  535.                         ShowErrorMsg(GetLastError(), _T("SetupDiRemoveDevice"));            
  536.                     wCount++;  
  537.                 }  
  538.             }  
  539.         }  
  540.         else  
  541.             break;  
  542.         wIdx++;  
  543.     }  
  544.   
  545.     if (wCount != 0)  
  546.         _tprintf(_T("UnInstall Successed\n"));  
  547.   
  548.     //销毁一个设备信息集合  
  549.     SetupDiDestroyDeviceInfoList(hDevInfo);  
  550.     InitialGlobalVar();  
  551.     return;  
  552. }  
  553.   
  554. //INF文件路径  
  555. const LPTSTR g_pInfPath = _T("C:\\Windows\\System32\\DriverStore\\FileRepository\\mydriver1.inf_x86_neutral_15204d1ef3d409a0\\mydriver1.inf");  
  556.   
  557. //入口函数  
  558. int _tmain(int argc, _TCHAR* argv[])  
  559. {  
  560.     CHAR szInfPath[MAX_PATH] = {0};  
  561.     UnicodeToAnsi(g_pInfPath, _tcslen(g_pInfPath), szInfPath, MAX_PATH);  
  562.     FILE* pInf;  
  563.     errno_t err;  
  564.   
  565.     if ((err=fopen_s(&pInf, szInfPath, "r"))!=0)  
  566.     {  
  567.         _tprintf(_T("can not open file %s\n"), g_pInfPath);  
  568.         return 0;  
  569.     }  
  570.   
  571.     // 获取INF文件数据  
  572.     GetINFData(pInf);  
  573.     fclose(pInf);  
  574.   
  575.     // 安装WDM驱动  
  576.     if(_tcscmp(argv[1], TEXT("-Install"))==0)  
  577.     {  
  578.         if (StartInstallWDMDriver(g_pInfPath) == FALSE)  
  579.         {  
  580.             _tprintf(_T("Start Install WMD Driver failed\n"));  
  581.             return 0;  
  582.         }  
  583.     }  
  584.     // 卸载WDM驱动  
  585.     else if(_tcscmp(argv[1], TEXT("-UnInstall"))==0)  
  586.     {  
  587.         for (WORD wLoop = 0; wLoop < g_wHardware; wLoop++)  
  588.             UninstallWDMDriver(g_strHardware[wLoop]);  
  589.     }  
  590.       
  591.     return 1;    
  592. }  
具体的SYS 和 INF文件 可参考:http://blog.csdn.net/whatday/article/details/9384577

测试结果:

把相应EXE及其SYS INF文件拷贝的WIN7虚拟机,打开CMD执行WinInstallWin.exe -Install 显示安装成功如图:


再用DeviceTree查看结果:

可以看到设备已经添加成功

在CMD中执行 WinInstallWin.exe -UnInstall 显示卸载成功 如图:

再次使用DeviceTree查看设备 需要刷新一下DeviceTree 结果如图:

先前的设备已经卸载掉了,到此WDM驱动的安装卸载就全部结束了

Mixcraft 多音轨音效混合器软件可以录制音频,安排循环,混音曲目,缀以MIDI和虚拟乐器,添加效果,比分和编辑视频,混合和掌握你的轨道创造抛光,专业组成。 Mixcraft是你的音乐制作梦想成真,瞬间将你的电脑变成一个储备齐全的专业音乐录音棚。 Acoustica Mixcraft Pro 产品特点 记录并创建无限数量的音频和MIDI音轨。 安排和得分的视频文件,添加转场,视觉效果,音乐,音效,和画外音提供方便。 包括超过6000专业制作音乐循环,并在各种流行款式的声音效果,从的dubstep到民谣摇滚。 包括11个虚拟乐器,从老式的模拟合成器,以优质的采样声乐器,以及录音室品质的声学和电鼓一个鼓舞人心的集合。 包括22个高品质的效果,从演播室标准,如混响,合唱和延迟,以超现实的吉他放大器模拟器,经典电子管均衡,人声还原,多频段压缩,等等。 功能强大,专业的功能包括ReWire的主机,多采取循环录像,时间伸缩和变调,无限硬件的输入和输出,多通道VSTis的支持,以及更多的支持。 具有高对比度的专业图形界面。 自定义循环库包含了超过6000免版税循环,并在一个巨大的各种风格的声音效果。 轻松导入您自己的循环文件和光盘循环进入循环库。 环库具有便捷的搜索工具来快速查找循环和声音特效。 适用于酸性™WAV和苹果车库乐队™AIFF循环。 记录多个MIDI和音频轨道同时进行。 钢琴卷帘窗来查看和编辑MIDI。 鼓的地图包括了Mixcraft的鼓乐器,加上许多流行的鼓应用。 符号工具,允许你创建,编辑,并在熟悉的音乐符号格式打印您的MIDI数据。 11强大的虚拟仪器,包括ACOUSTICA仪器通用MIDI采样库,扩展仪器样本库,工作室鼓样品采集,休息室蜥蜴届复古电钢琴,VB3音轮风琴,ComboV和ComboF经典的晶体管器官模拟器,MiniMogueVA单声道模拟合成器,和弦弥赛亚模拟合成器,Alien303贝司合成器和脉冲复音模拟合成器。 25个高品质的效果,包括Pultronic管情商,该款机型的经典电子管均衡器在工作室遍布世界各地,并theShred音箱模拟器,5经典功放磁头,17个内阁模型和6震撼效果的完整套件。 内置可对每一个音轨的吉他调谐器。 保存和加载完整的音频效果链,具备许多优良的效果链预置包括在内。 创建复杂的虚拟仪器设置的叠加和分割多个虚拟合成器和效果。设置键位,力度灵敏度,换位,平移和体积每件乐器。 新增无限的VSTi™仪器,VST™和DirectX™效果。 路线MIDI音轨数据,音频效果(如声码器和音高修正效果)。 视频轨允许装载和视频文件编辑。容易交叉淡入淡出从一个视频剪辑到另一个。混音的音频,添加配乐,并毫不费力地将视频项目渲染到一个新的视频文件。 强大的视频功能包括静止图像的进口,自动化的效果和过渡,和移动的文本。 缩混的MP3,WAV,高品质压缩OGG等音频文件类型。 选项直接录制到高品质压缩OGG文件。这是理想的合作者交换在互联网上项目,笔记本电脑用户,学校,和任何人都长的录音讲话或会议。 插入时间和删除时间功能移动所有的声音,自动化和标记,以便您可以添加或删除你的歌一整节。 燃烧你的混音的CD只需点击一下鼠标。 Acoustica Mixcraft Pro 声音引擎 波器(WDM),支持ASIO™,WaveRT和WaveRT独占模式低延迟音频支持。 WaveRT独占模式(适用于Windows 7及以上)提供大多数的音频硬件超低延迟,固体传声性能,而无需任何特殊的声卡驱动程序。随着WaveRT独占模式,Mixcraft可以与音频硬件直接连接,绕过操作系统的低延迟的音频性能,无需任何特殊的驱动程序。 MIDI输入和输出的支持。将与任何USB MIDI键盘或连接到MIDI接口的任何文书工作。 交通控制,效果控制和仪器控制MIDI控制面的支持。 32位SSE2优化的声音引擎支持录制和播放的广播质量的音频,高达192 kHz和32位。 时间伸展任何声音从25%到400%与FlexAudio™而不影响音调。 记入/记出录音。 循环记录有多个需要。 移调的声音从-24到+12半音! 使用无限数量的曲目,乐器和效果。 自动检测节拍位置,钥匙和进口歌曲的节奏。 导入WAV,AIF,OGG,WMA和MP3文件! 降低噪音水平,或完全消除它具有内置的可在每个音频剪辑降噪。 支持多达16个处理器核心采用了当今最先进的多处理器计算机充分利用。 塑造每个声音的音量,声像和谐振滤波器具有无限的信封分。 支持DirectX™&VST™的影响,包括插件延迟补偿。 支持VST乐器与多个输出。 ReWire的主机允许你同步与Mixcraft其它音乐应用。 Acoustica Mixcraft Pro 界面 新的自动化功能提供任
1.为什么要使用海豚蓝牙音箱,能带给我什么样的音乐体验 目前市面上的蓝牙音箱基本上是一个全频段的喇叭来播放CD音质的音乐,如果是立体声的是不能通过一个喇叭来播放,无法实现空间上的立体效果,必须像漫步者的2.1级音箱一样,总共有有三个喇叭,两个卫星箱一个超重低音音箱来重现立体声,但传统的音箱体积庞大携带性比较差,于是海豚蓝牙ASIO驱动软件应运而生,解决这些让人困扰的问题。 2.使用海豚蓝牙ASIO软件有什么样的音乐体验呢? a.声音来源干净无Windows操作系统干扰,由于采用的是独占式音频通道,音频流采用的是来自于Windows的内核流,没有经过Windows的过滤器,声音采样值直接输出到声卡,声音输出比较干净未遭到破坏,满足音乐发烧友的完美音质的口味。 b.直接驱动多个蓝牙音箱实现直正的立体声效果,让您听不出来音箱放在何处,实现空间上的3D环绕效果,如果采用的蓝牙箱重低音效果不错的话,能够带给你无法语言表达的震撼效果,您可以试试播放《天之大-韩红》这首曲子。 c.适合于户外开展训练活动,您不需要携带笨重的音箱进行彩排训练,效果可以与专业级音箱相媲美,无需220V电源也可以把活动搞起来! 3. 安装必读 本版本软件是PC版本,需要安装在Windows XP/WIN7/WIN8/WIN10 操作系统上,支持主流的音乐播放软件,如百度音乐、QQ音乐、酷狗音乐、foobar2000等,只要音乐播放软件支持ASIO驱动就可以使用本软件。 硬件要求: a.适配绝大部分市面上标准音箱,像科凌的A8/A5、爱度、力勤、雅兰仕等音箱,尽量选用同款同型号音箱,否则输出延时差别较大影响音乐体验。 b.笔记本/台式机需要支持蓝牙,没有蓝牙功能可以到淘宝上购买蓝牙适配器,插在USB上即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值