Dodal sem podporo za nameščanje profilov WLAN. Ampak odstranjevanje kljub mojim velikim naporom še ne deluje.
Verzijo MSICA sem nastavil na 1.0-pre2.
This commit is contained in:
@@ -2,7 +2,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: MSICA\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-03-21 18:37+0100\n"
|
||||
"POT-Creation-Date: 2014-03-22 13:34+0100\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Simon Rozman <simon.rozman@amebis.si>\n"
|
||||
"Language-Team: Amebis, d. o. o., Kamnik <simon.rozman@amebis.si>\n"
|
||||
@@ -84,6 +84,13 @@ msgstr "Digitalno potrdilo: [1]"
|
||||
msgid "Configuring services"
|
||||
msgstr "Nastavljanje servisov"
|
||||
|
||||
#: MSIBuild/En.Win32.Debug.ActionText-2.idtx:7
|
||||
#: MSIBuild/En.Win32.Release.ActionText-2.idtx:7
|
||||
#: MSIBuild/En.x64.Debug.ActionText-2.idtx:7
|
||||
#: MSIBuild/En.x64.Release.ActionText-2.idtx:7
|
||||
msgid "Evaluating WLAN profiles"
|
||||
msgstr "Pregled profilov WLAN"
|
||||
|
||||
#: MSIBuild/En.Win32.Debug.ActionText-2.idtx:4
|
||||
#: MSIBuild/En.Win32.Release.ActionText-2.idtx:4
|
||||
#: MSIBuild/En.x64.Debug.ActionText-2.idtx:4
|
||||
@@ -98,6 +105,13 @@ msgstr "Nameščanje digitalnih potrdil"
|
||||
msgid "Registering scheduled tasks"
|
||||
msgstr "Registracija razporejenih opravil"
|
||||
|
||||
#: MSIBuild/En.Win32.Debug.ActionText-2.idtx:8
|
||||
#: MSIBuild/En.Win32.Release.ActionText-2.idtx:8
|
||||
#: MSIBuild/En.x64.Debug.ActionText-2.idtx:8
|
||||
#: MSIBuild/En.x64.Release.ActionText-2.idtx:8
|
||||
msgid "Removing WLAN profiles"
|
||||
msgstr "Odstranjevanje profilov WLAN"
|
||||
|
||||
#: MSIBuild/En.Win32.Debug.ActionText-2.idtx:6
|
||||
#: MSIBuild/En.Win32.Release.ActionText-2.idtx:6
|
||||
#: MSIBuild/En.x64.Debug.ActionText-2.idtx:6
|
||||
@@ -111,3 +125,25 @@ msgstr "Razporejeno opravilo: [1]"
|
||||
#: MSIBuild/En.x64.Release.ActionText-2.idtx:5
|
||||
msgid "Service: [1]"
|
||||
msgstr "Servis: [1]"
|
||||
|
||||
#: MSIBuild/En.Win32.Debug.ActionText-2.idtx:9
|
||||
#: MSIBuild/En.Win32.Release.ActionText-2.idtx:9
|
||||
#: MSIBuild/En.x64.Debug.ActionText-2.idtx:9
|
||||
#: MSIBuild/En.x64.Release.ActionText-2.idtx:9
|
||||
msgid "Setting WLAN profiles"
|
||||
msgstr "Nastavljanje profilov WLAN"
|
||||
|
||||
#: MSIBuild/En.Win32.Debug.ActionText-2.idtx:7
|
||||
#: MSIBuild/En.Win32.Debug.ActionText-2.idtx:8
|
||||
#: MSIBuild/En.Win32.Debug.ActionText-2.idtx:9
|
||||
#: MSIBuild/En.Win32.Release.ActionText-2.idtx:7
|
||||
#: MSIBuild/En.Win32.Release.ActionText-2.idtx:8
|
||||
#: MSIBuild/En.Win32.Release.ActionText-2.idtx:9
|
||||
#: MSIBuild/En.x64.Debug.ActionText-2.idtx:7
|
||||
#: MSIBuild/En.x64.Debug.ActionText-2.idtx:8
|
||||
#: MSIBuild/En.x64.Debug.ActionText-2.idtx:9
|
||||
#: MSIBuild/En.x64.Release.ActionText-2.idtx:7
|
||||
#: MSIBuild/En.x64.Release.ActionText-2.idtx:8
|
||||
#: MSIBuild/En.x64.Release.ActionText-2.idtx:9
|
||||
msgid "WLAN profile: [1]"
|
||||
msgstr "Profil WLAN: [1]"
|
||||
|
||||
@@ -59,6 +59,11 @@ TaskTrigger DaysOfMonth Y DoubleInteger Specifies the day of the month a ta
|
||||
TaskTrigger WeekOfMonth Y Integer 1;2;3;4;5 Specifies the week of the month when the task runs. This value is exclusive and is one of the following: 1=The task will run between the first and seventh day of the month, 2=The task will run between the eighth and 14th day of the month, 3=The task will run between the 15th and 21st day of the month, 4=The task will run between the 22nd and 28th of the month, 5=The task will run between the last seven days of the month.
|
||||
TaskTrigger MonthsOfYear Y 0 4095 Integer Specifies the month(s) when the task runs. This value is a combination of the following values: 1=Jan, 2=Feb, 4=Mar, 8=Apr, 16=May, 32=Jun, 64=Jul, 128=Aug, 256=Sep, 512=Oct, 1024=Nov, 2048=Dec.
|
||||
TaskTrigger Task_ N ScheduledTask 1 Identifier Key of the Trigger's task.
|
||||
WLANProfile WLANProfile N Identifier Primary key, non-localized token.
|
||||
WLANProfile Name N Formatted Profile name
|
||||
WLANProfile Binary_ N Binary 1 Identifier The profile XML file. The binary information is looked up from the Binary Table.
|
||||
WLANProfile Condition Y Condition Optional expression which skips the profile if evaluates to expFalse. If the expression syntax is invalid, the engine will terminate, returning iesBadActionData.
|
||||
WLANProfile Component_ N Component 1 Identifier Component the profile is part of.
|
||||
<<NOKEEP
|
||||
|
||||
|
||||
@@ -76,6 +81,9 @@ s$(MSIBUILD_LENGTH_ID) L0 L0
|
||||
CertificatesExec Installing certificates Certificate: [1]
|
||||
ServiceConfigExec Configuring services Service: [1]
|
||||
ScheduledTasksExec Registering scheduled tasks Scheduled task: [1]
|
||||
EvaluateWLANProfiles Evaluating WLAN profiles WLAN profile: [1]
|
||||
RemoveWLANProfilesExec Removing WLAN profiles WLAN profile: [1]
|
||||
SetWLANProfilesExec Setting WLAN profiles WLAN profile: [1]
|
||||
<<NOKEEP
|
||||
|
||||
"De.$(PLAT).$(CFG).ActionText-2.idt" : "En.$(PLAT).$(CFG).ActionText-2.idtx" "..\L10N\de_DE.po"
|
||||
@@ -148,6 +156,13 @@ ScheduledTasksEval 1 binMSICA.dll ScheduledTasksEval
|
||||
ScheduledTasksExec 3073 binMSICA.dll ExecuteSequence
|
||||
ScheduledTasksRollback 3329 binMSICA.dll ExecuteSequence
|
||||
ScheduledTasksCommit 3585 binMSICA.dll ExecuteSequence
|
||||
EvaluateWLANProfiles 1 binMSICA.dll EvaluateWLANProfiles
|
||||
RemoveWLANProfilesExec 3073 binMSICA.dll ExecuteSequence
|
||||
RemoveWLANProfilesRollback 3329 binMSICA.dll ExecuteSequence
|
||||
RemoveWLANProfilesCommit 3585 binMSICA.dll ExecuteSequence
|
||||
SetWLANProfilesExec 3073 binMSICA.dll ExecuteSequence
|
||||
SetWLANProfilesRollback 3329 binMSICA.dll ExecuteSequence
|
||||
SetWLANProfilesCommit 3585 binMSICA.dll ExecuteSequence
|
||||
<<NOKEEP
|
||||
|
||||
|
||||
@@ -162,6 +177,13 @@ All :: "$(LANG).$(PLAT).$(CFG).InstallExecuteSequence-1.idt"
|
||||
Action Condition Sequence
|
||||
s$(MSIBUILD_LENGTH_ID) S255 I2
|
||||
InstallExecuteSequence Action
|
||||
EvaluateWLANProfiles 1650
|
||||
RemoveWLANProfilesRollback 1850
|
||||
RemoveWLANProfilesExec 1851
|
||||
RemoveWLANProfilesCommit 1852
|
||||
SetWLANProfilesRollback 6150
|
||||
SetWLANProfilesExec 6151
|
||||
SetWLANProfilesCommit 6152
|
||||
CertificatesEval 6576
|
||||
CertificatesRollback 6577
|
||||
CertificatesExec 6578
|
||||
@@ -219,6 +241,20 @@ TaskTrigger Trigger
|
||||
<<NOKEEP
|
||||
|
||||
|
||||
######################################################################
|
||||
# WLANProfile
|
||||
|
||||
All :: "$(LANG).$(PLAT).$(CFG).WLANProfile-1.idt"
|
||||
|
||||
"$(LANG).$(PLAT).$(CFG).WLANProfile-1.idt" : "Makefile" "..\..\..\include\MSIBuildCfg.mak"
|
||||
-if exist $@ del /f /q $@
|
||||
move /y << $@ > NUL
|
||||
WLANProfile Name Binary_ Condition Component_
|
||||
s$(MSIBUILD_LENGTH_ID) l255 s$(MSIBUILD_LENGTH_ID) S255 s$(MSIBUILD_LENGTH_ID)
|
||||
WLANProfile WLANProfile
|
||||
<<NOKEEP
|
||||
|
||||
|
||||
######################################################################
|
||||
# Build MSM module!
|
||||
######################################################################
|
||||
|
||||
202
MSICA/MSICA.cpp
202
MSICA/MSICA.cpp
@@ -1,15 +1,18 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#pragma comment(lib, "wlanapi.lib")
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Local constants
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define MSICA_CERT_TICK_SIZE (4*1024)
|
||||
#define MSICA_SVC_SET_START_TICK_SIZE (1*1024)
|
||||
#define MSICA_SVC_START_TICK_SIZE (1*1024)
|
||||
#define MSICA_SVC_STOP_TICK_SIZE (1*1024)
|
||||
#define MSICA_CERT_TICK_SIZE ( 4*1024)
|
||||
#define MSICA_SVC_SET_START_TICK_SIZE ( 1*1024)
|
||||
#define MSICA_SVC_START_TICK_SIZE ( 1*1024)
|
||||
#define MSICA_SVC_STOP_TICK_SIZE ( 1*1024)
|
||||
#define MSICA_TASK_TICK_SIZE (16*1024)
|
||||
#define MSICA_WLAN_PROFILE_TICK_SIZE ( 2*1024)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -63,7 +66,6 @@ UINT MSICA_API CertificatesEval(MSIHANDLE hInstall)
|
||||
// Execute query!
|
||||
uiResult = ::MsiViewExecute(hViewCert, NULL);
|
||||
if (uiResult == NO_ERROR) {
|
||||
//ATL::CAtlString sComponent;
|
||||
ATL::CAtlStringW sStore;
|
||||
int iFlags, iEncoding;
|
||||
ATL::CAtlArray<BYTE> binCert;
|
||||
@@ -449,6 +451,196 @@ UINT MSICA_API ScheduledTasksEval(MSIHANDLE hInstall)
|
||||
}
|
||||
|
||||
|
||||
UINT MSICA_API EvaluateWLANProfiles(MSIHANDLE hInstall)
|
||||
{
|
||||
//::MessageBox(NULL, _T(__FUNCTION__), _T("MSICA"), MB_OK);
|
||||
|
||||
UINT uiResult;
|
||||
BOOL bIsCoInitialized = SUCCEEDED(::CoInitialize(NULL));
|
||||
MSICA::COpList olExecuteInstall, olExecuteRemove;
|
||||
BOOL bRollbackEnabled;
|
||||
PMSIHANDLE
|
||||
hDatabase,
|
||||
hRecordProg = ::MsiCreateRecord(3);
|
||||
ATL::CAtlString sValue;
|
||||
|
||||
// Check and add the rollback enabled state.
|
||||
uiResult = ::MsiGetProperty(hInstall, _T("RollbackDisabled"), sValue);
|
||||
bRollbackEnabled = uiResult == NO_ERROR ?
|
||||
_ttoi(sValue) || !sValue.IsEmpty() && _totlower(sValue.GetAt(0)) == _T('y') ? FALSE : TRUE :
|
||||
TRUE;
|
||||
olExecuteInstall.AddTail(new MSICA::COpRollbackEnable(bRollbackEnabled));
|
||||
olExecuteRemove.AddTail(new MSICA::COpRollbackEnable(bRollbackEnabled));
|
||||
|
||||
// Open MSI database.
|
||||
hDatabase = ::MsiGetActiveDatabase(hInstall);
|
||||
if (hDatabase) {
|
||||
// Check if WLANProfile table exists. If it doesn't exist, there's nothing to do.
|
||||
MSICONDITION condition = ::MsiDatabaseIsTablePersistent(hDatabase, _T("WLANProfile"));
|
||||
if (condition == MSICONDITION_FALSE || condition == MSICONDITION_TRUE) {
|
||||
PMSIHANDLE hViewProfile;
|
||||
|
||||
// Prepare a query to get a list/view of profiles.
|
||||
uiResult = ::MsiDatabaseOpenView(hDatabase, _T("SELECT Binary_,Name,Condition,Component_ FROM WLANProfile"), &hViewProfile);
|
||||
if (uiResult == NO_ERROR) {
|
||||
// Execute query!
|
||||
uiResult = ::MsiViewExecute(hViewProfile, NULL);
|
||||
if (uiResult == NO_ERROR) {
|
||||
DWORD dwError, dwNegotiatedVersion;
|
||||
HANDLE hClientHandle;
|
||||
|
||||
// Open WLAN handle.
|
||||
dwError = ::WlanOpenHandle(2, NULL, &dwNegotiatedVersion, &hClientHandle);
|
||||
if (dwError == NO_ERROR) {
|
||||
WLAN_INTERFACE_INFO_LIST *pInterfaceList;
|
||||
|
||||
// Get a list of WLAN interfaces.
|
||||
dwError = ::WlanEnumInterfaces(hClientHandle, NULL, &pInterfaceList);
|
||||
if (dwError == NO_ERROR) {
|
||||
ATL::CAtlStringW sName, sProfileXML;
|
||||
ATL::CAtlArray<BYTE> binProfile;
|
||||
|
||||
for (;;) {
|
||||
PMSIHANDLE hRecord;
|
||||
INSTALLSTATE iInstalled, iAction;
|
||||
int iTick = 0;
|
||||
DWORD i;
|
||||
|
||||
// Fetch one record from the view.
|
||||
uiResult = ::MsiViewFetch(hViewProfile, &hRecord);
|
||||
if (uiResult == ERROR_NO_MORE_ITEMS) {
|
||||
uiResult = NO_ERROR;
|
||||
break;
|
||||
} else if (uiResult != NO_ERROR)
|
||||
break;
|
||||
|
||||
// Read and evaluate profile's condition.
|
||||
uiResult = ::MsiRecordGetString(hRecord, 3, sValue);
|
||||
if (uiResult != NO_ERROR) break;
|
||||
condition = ::MsiEvaluateCondition(hInstall, sValue);
|
||||
if (condition == MSICONDITION_FALSE)
|
||||
continue;
|
||||
else if (condition == MSICONDITION_ERROR) {
|
||||
uiResult = ERROR_INVALID_FIELD;
|
||||
break;
|
||||
}
|
||||
|
||||
// Read profile's name.
|
||||
uiResult = ::MsiRecordGetString(hRecord, 2, sName);
|
||||
if (uiResult != NO_ERROR) break;
|
||||
|
||||
// Read profile's component ID.
|
||||
uiResult = ::MsiRecordGetString(hRecord, 4, sValue);
|
||||
if (uiResult != NO_ERROR) break;
|
||||
|
||||
// Get the component state.
|
||||
uiResult = ::MsiGetComponentState(hInstall, sValue, &iInstalled, &iAction);
|
||||
if (uiResult != NO_ERROR) break;
|
||||
|
||||
if (iAction >= INSTALLSTATE_LOCAL) {
|
||||
PMSIHANDLE hViewBinary, hRecordBin;
|
||||
LPCWSTR pProfileStr;
|
||||
SIZE_T nCount;
|
||||
|
||||
// Perform another query to get profile's binary data.
|
||||
uiResult = ::MsiDatabaseOpenView(hDatabase, _T("SELECT Data FROM Binary WHERE Name=?"), &hViewBinary);
|
||||
if (uiResult != NO_ERROR) break;
|
||||
|
||||
// Execute query!
|
||||
uiResult = ::MsiViewExecute(hViewBinary, hRecord);
|
||||
if (uiResult != NO_ERROR) break;
|
||||
|
||||
// Fetch one record from the view.
|
||||
uiResult = ::MsiViewFetch(hViewBinary, &hRecordBin);
|
||||
if (uiResult == NO_ERROR)
|
||||
uiResult = ::MsiRecordGetStream(hRecordBin, 1, binProfile);
|
||||
::MsiViewClose(hViewBinary);
|
||||
if (uiResult != NO_ERROR) break;
|
||||
|
||||
// Convert CAtlArray<BYTE> to CAtlStringW.
|
||||
pProfileStr = (LPCWSTR)binProfile.GetData();
|
||||
nCount = binProfile.GetCount()/sizeof(WCHAR);
|
||||
|
||||
if (nCount < 1 || pProfileStr[0] != 0xfeff) {
|
||||
// The profile XML is not UTF-16 encoded.
|
||||
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_WLAN_PROFILE_NOT_UTF16);
|
||||
::MsiRecordSetStringW(hRecordProg, 2, sName );
|
||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
||||
uiResult = ERROR_INSTALL_USEREXIT;
|
||||
}
|
||||
sProfileXML.SetString(pProfileStr + 1, (int)nCount - 1);
|
||||
|
||||
for (i = 0; i < pInterfaceList->dwNumberOfItems; i++) {
|
||||
// Check for not ready state in interface.
|
||||
if (pInterfaceList->InterfaceInfo[i].isState != wlan_interface_state_not_ready) {
|
||||
olExecuteInstall.AddTail(new MSICA::COpWLANProfileSet(pInterfaceList->InterfaceInfo[i].InterfaceGuid, sName, sProfileXML, MSICA_WLAN_PROFILE_TICK_SIZE));
|
||||
iTick += MSICA_WLAN_PROFILE_TICK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
// The amount of tick space to add for each profile to progress indicator.
|
||||
::MsiRecordSetInteger(hRecordProg, 1, 3 );
|
||||
::MsiRecordSetInteger(hRecordProg, 2, iTick);
|
||||
if (::MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL) { uiResult = ERROR_INSTALL_USEREXIT; break; }
|
||||
} else if (iAction >= INSTALLSTATE_REMOVED) {
|
||||
// Component is installed, but should be degraded to advertised/removed. Delete the profile from all interfaces.
|
||||
for (i = 0; i < pInterfaceList->dwNumberOfItems; i++) {
|
||||
// Check for not ready state in interface.
|
||||
if (pInterfaceList->InterfaceInfo[i].isState != wlan_interface_state_not_ready) {
|
||||
olExecuteRemove.AddTail(new MSICA::COpWLANProfileDelete(pInterfaceList->InterfaceInfo[i].InterfaceGuid, sName, MSICA_WLAN_PROFILE_TICK_SIZE));
|
||||
iTick += MSICA_WLAN_PROFILE_TICK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
// The amount of tick space to add for each profile to progress indicator.
|
||||
::MsiRecordSetInteger(hRecordProg, 1, 3 );
|
||||
::MsiRecordSetInteger(hRecordProg, 2, iTick);
|
||||
if (::MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL) { uiResult = ERROR_INSTALL_USEREXIT; break; }
|
||||
}
|
||||
}
|
||||
::WlanFreeMemory(pInterfaceList);
|
||||
}
|
||||
::WlanCloseHandle(hClientHandle, NULL);
|
||||
} else {
|
||||
uiResult = ERROR_INSTALL_WLAN_HANDLE_OPEN;
|
||||
::MsiRecordSetInteger(hRecordProg, 1, uiResult);
|
||||
::MsiRecordSetInteger(hRecordProg, 2, dwError);
|
||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
||||
}
|
||||
::MsiViewClose(hViewProfile);
|
||||
|
||||
if (uiResult == NO_ERROR) {
|
||||
// Save the sequences.
|
||||
uiResult = MSICA::SaveSequence(hInstall, _T("SetWLANProfilesExec"), _T("SetWLANProfilesCommit"), _T("SetWLANProfilesRollback"), olExecuteInstall);
|
||||
uiResult = MSICA::SaveSequence(hInstall, _T("RemoveWLANProfilesExec"), _T("RemoveWLANProfilesCommit"), _T("RemoveWLANProfilesRollback"), olExecuteRemove);
|
||||
} else if (uiResult != ERROR_INSTALL_USEREXIT) {
|
||||
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_OPLIST_CREATE);
|
||||
::MsiRecordSetInteger(hRecordProg, 2, uiResult );
|
||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
||||
}
|
||||
} else {
|
||||
::MsiRecordSetInteger(hRecordProg, 1, uiResult);
|
||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
||||
}
|
||||
} else {
|
||||
::MsiRecordSetInteger(hRecordProg, 1, uiResult);
|
||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uiResult = ERROR_INSTALL_DATABASE_OPEN;
|
||||
::MsiRecordSetInteger(hRecordProg, 1, uiResult);
|
||||
::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
||||
}
|
||||
|
||||
olExecuteInstall.Free();
|
||||
olExecuteRemove.Free();
|
||||
|
||||
if (bIsCoInitialized) ::CoUninitialize();
|
||||
return uiResult;
|
||||
}
|
||||
|
||||
|
||||
UINT MSICA_API ExecuteSequence(MSIHANDLE hInstall)
|
||||
{
|
||||
//::MessageBox(NULL, _T(__FUNCTION__), _T("MSICA"), MB_OK);
|
||||
|
||||
@@ -27,6 +27,9 @@ extern "C" {
|
||||
UINT MSICA_API CertificatesEval(MSIHANDLE hInstall);
|
||||
UINT MSICA_API ServiceConfigEval(MSIHANDLE hInstall);
|
||||
UINT MSICA_API ScheduledTasksEval(MSIHANDLE hInstall);
|
||||
UINT MSICA_API EvaluateWLANProfiles(MSIHANDLE hInstall);
|
||||
UINT MSICA_API RemoveWLANProfiles(MSIHANDLE hInstall);
|
||||
UINT MSICA_API SetWLANProfiles(MSIHANDLE hInstall);
|
||||
UINT MSICA_API ExecuteSequence(MSIHANDLE hInstall);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <corerror.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <wlanapi.h>
|
||||
|
||||
#include "..\MSICALib\MSICALib.h"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user