Wlanapi.dll is accessed dynamically now (since not present on Windows Server by default)

This commit is contained in:
Simon Rozman 2016-03-11 12:44:45 +01:00
parent 4bb46b2ff1
commit d64d5d31ab
4 changed files with 96 additions and 72 deletions

View File

@ -59,6 +59,7 @@ i2 L0
2571 Error [3] changing service "[2]" start type. Please, contact your support personnel. 2571 Error [3] changing service "[2]" start type. Please, contact your support personnel.
2572 Error [3] starting service "[2]". Please, contact your support personnel. 2572 Error [3] starting service "[2]". Please, contact your support personnel.
2573 Error [3] stopping service "[2]". Please, contact your support personnel. 2573 Error [3] stopping service "[2]". Please, contact your support personnel.
2580 Error installing WLAN profiles, because WLAN is not installed. Please, install Wireless LAN Service Windows feature, or contact your support personnel.
2579 Error opening WLAN handle, because WLAN AutoConfig service is not started. Please, enable and start WLAN AutoConfig service, or contact your support personnel. 2579 Error opening WLAN handle, because WLAN AutoConfig service is not started. Please, enable and start WLAN AutoConfig service, or contact your support personnel.
2577 Error [2] opening WLAN handle. Please, contact your support personnel. 2577 Error [2] opening WLAN handle. Please, contact your support personnel.
2578 WLAN profile "[2]" XML data is not UTF-16 encoded. Please, contact your support personnel. 2578 WLAN profile "[2]" XML data is not UTF-16 encoded. Please, contact your support personnel.

View File

@ -30,7 +30,7 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Error codes (next unused 2580L) // Error codes (next unused 2581L)
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
#define ERROR_INSTALL_DATABASE_OPEN 2550L #define ERROR_INSTALL_DATABASE_OPEN 2550L
@ -57,6 +57,7 @@
#define ERROR_INSTALL_SVC_SET_START 2571L #define ERROR_INSTALL_SVC_SET_START 2571L
#define ERROR_INSTALL_SVC_START 2572L #define ERROR_INSTALL_SVC_START 2572L
#define ERROR_INSTALL_SVC_STOP 2573L #define ERROR_INSTALL_SVC_STOP 2573L
#define ERROR_INSTALL_WLAN_NOT_INSTALLED 2580L
#define ERROR_INSTALL_WLAN_SVC_NOT_STARTED 2579L #define ERROR_INSTALL_WLAN_SVC_NOT_STARTED 2579L
#define ERROR_INSTALL_WLAN_HANDLE_OPEN 2577L #define ERROR_INSTALL_WLAN_HANDLE_OPEN 2577L
#define ERROR_INSTALL_WLAN_PROFILE_NOT_UTF16 2578L #define ERROR_INSTALL_WLAN_PROFILE_NOT_UTF16 2578L

View File

@ -19,8 +19,6 @@
#include "stdafx.h" #include "stdafx.h"
#pragma comment(lib, "wlanapi.lib")
namespace MSICA { namespace MSICA {
@ -46,45 +44,52 @@ COpWLANProfileDelete::COpWLANProfileDelete(const GUID &guidInterface, LPCWSTR ps
HRESULT COpWLANProfileDelete::Execute(CSession *pSession) HRESULT COpWLANProfileDelete::Execute(CSession *pSession)
{ {
DWORD dwError, dwNegotiatedVersion; if (::pfnWlanOpenHandle && ::pfnWlanCloseHandle && ::pfnWlanGetProfile && ::pfnWlanDeleteProfile && ::pfnWlanFreeMemory) {
HANDLE hClientHandle; DWORD dwError, dwNegotiatedVersion;
HANDLE hClientHandle;
dwError = ::WlanOpenHandle(2, NULL, &dwNegotiatedVersion, &hClientHandle); dwError = ::pfnWlanOpenHandle(2, NULL, &dwNegotiatedVersion, &hClientHandle);
if (dwError == NO_ERROR) { if (dwError == NO_ERROR) {
if (pSession->m_bRollbackEnabled) { if (pSession->m_bRollbackEnabled) {
LPWSTR pszProfileXML = NULL; LPWSTR pszProfileXML = NULL;
DWORD dwFlags = 0, dwGrantedAccess = 0; DWORD dwFlags = 0, dwGrantedAccess = 0;
// Get profile settings as XML first. // Get profile settings as XML first.
dwError = ::WlanGetProfile(hClientHandle, &m_guidInterface, m_sValue, NULL, &pszProfileXML, &dwFlags, &dwGrantedAccess); dwError = ::pfnWlanGetProfile(hClientHandle, &m_guidInterface, m_sValue, NULL, &pszProfileXML, &dwFlags, &dwGrantedAccess);
if (dwError == NO_ERROR) {
// Delete the profile.
dwError = ::WlanDeleteProfile(hClientHandle, &m_guidInterface, m_sValue, NULL);
if (dwError == NO_ERROR) { if (dwError == NO_ERROR) {
// Order rollback action to recreate it. // Delete the profile.
pSession->m_olRollback.AddHead(new COpWLANProfileSet(m_guidInterface, dwFlags, m_sValue, pszProfileXML)); dwError = ::pfnWlanDeleteProfile(hClientHandle, &m_guidInterface, m_sValue, NULL);
if (dwError == NO_ERROR) {
// Order rollback action to recreate it.
pSession->m_olRollback.AddHead(new COpWLANProfileSet(m_guidInterface, dwFlags, m_sValue, pszProfileXML));
}
::pfnWlanFreeMemory(pszProfileXML);
} }
::WlanFreeMemory(pszProfileXML); } else {
// Delete the profile.
dwError = ::pfnWlanDeleteProfile(hClientHandle, &m_guidInterface, m_sValue, NULL);
} }
} else { ::pfnWlanCloseHandle(hClientHandle, NULL);
// Delete the profile.
dwError = ::WlanDeleteProfile(hClientHandle, &m_guidInterface, m_sValue, NULL);
} }
::WlanCloseHandle(hClientHandle, NULL);
}
if (dwError == NO_ERROR || dwError == ERROR_NOT_FOUND) if (dwError == NO_ERROR || dwError == ERROR_NOT_FOUND)
return S_OK; return S_OK;
else { else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4); PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
ATL::CAtlStringW sGUID; ATL::CAtlStringW sGUID;
GuidToString(&m_guidInterface, sGUID); GuidToString(&m_guidInterface, sGUID);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_WLAN_PROFILE_DELETE); ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_WLAN_PROFILE_DELETE);
::MsiRecordSetStringW(hRecordProg, 2, sGUID ); ::MsiRecordSetStringW(hRecordProg, 2, sGUID );
::MsiRecordSetStringW(hRecordProg, 3, m_sValue ); ::MsiRecordSetStringW(hRecordProg, 3, m_sValue );
::MsiRecordSetInteger(hRecordProg, 4, dwError ); ::MsiRecordSetInteger(hRecordProg, 4, dwError );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError);
}
} else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(1);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_WLAN_NOT_INSTALLED);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError); return E_NOTIMPL;
} }
} }
@ -103,50 +108,57 @@ COpWLANProfileSet::COpWLANProfileSet(const GUID &guidInterface, DWORD dwFlags, L
HRESULT COpWLANProfileSet::Execute(CSession *pSession) HRESULT COpWLANProfileSet::Execute(CSession *pSession)
{ {
DWORD dwError, dwNegotiatedVersion; if (::pfnWlanOpenHandle && ::pfnWlanCloseHandle && ::pfnWlanSetProfile && ::pfnWlanReasonCodeToString) {
HANDLE hClientHandle; DWORD dwError, dwNegotiatedVersion;
WLAN_REASON_CODE wlrc = 0; HANDLE hClientHandle;
WLAN_REASON_CODE wlrc = 0;
{ {
// Delete existing profile first. // Delete existing profile first.
// Since deleting a profile is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it. // Since deleting a profile is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it.
// Don't worry, COpWLANProfileDelete::Execute() returns S_OK if profile doesn't exist. // Don't worry, COpWLANProfileDelete::Execute() returns S_OK if profile doesn't exist.
COpWLANProfileDelete opDelete(m_guidInterface, m_sValue); COpWLANProfileDelete opDelete(m_guidInterface, m_sValue);
HRESULT hr = opDelete.Execute(pSession); HRESULT hr = opDelete.Execute(pSession);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
}
dwError = ::WlanOpenHandle(2, NULL, &dwNegotiatedVersion, &hClientHandle);
if (dwError == NO_ERROR) {
// Set the profile.
dwError = ::WlanSetProfile(hClientHandle, &m_guidInterface, m_dwFlags, m_sProfileXML, NULL, TRUE, NULL, &wlrc);
if (dwError == NO_ERROR && pSession->m_bRollbackEnabled) {
// Order rollback action to delete it.
pSession->m_olRollback.AddHead(new COpWLANProfileDelete(m_guidInterface, m_sValue));
} }
::WlanCloseHandle(hClientHandle, NULL);
}
if (dwError == NO_ERROR) dwError = ::pfnWlanOpenHandle(2, NULL, &dwNegotiatedVersion, &hClientHandle);
return S_OK; if (dwError == NO_ERROR) {
else { // Set the profile.
PMSIHANDLE hRecordProg = ::MsiCreateRecord(5); dwError = ::pfnWlanSetProfile(hClientHandle, &m_guidInterface, m_dwFlags, m_sProfileXML, NULL, TRUE, NULL, &wlrc);
ATL::CAtlStringW sGUID, sReason; if (dwError == NO_ERROR && pSession->m_bRollbackEnabled) {
DWORD dwSize = 1024, dwResult; // Order rollback action to delete it.
LPWSTR szBuffer = sReason.GetBuffer(dwSize); pSession->m_olRollback.AddHead(new COpWLANProfileDelete(m_guidInterface, m_sValue));
}
::pfnWlanCloseHandle(hClientHandle, NULL);
}
GuidToString(&m_guidInterface, sGUID); if (dwError == NO_ERROR)
dwResult = ::WlanReasonCodeToString(wlrc, dwSize, szBuffer, NULL); return S_OK;
sReason.ReleaseBuffer(dwSize); else {
if (dwResult != NO_ERROR) sReason.Format(L"0x%x", wlrc); PMSIHANDLE hRecordProg = ::MsiCreateRecord(5);
ATL::CAtlStringW sGUID, sReason;
DWORD dwSize = 1024, dwResult;
LPWSTR szBuffer = sReason.GetBuffer(dwSize);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_WLAN_PROFILE_SET); GuidToString(&m_guidInterface, sGUID);
::MsiRecordSetStringW(hRecordProg, 2, sGUID ); dwResult = ::pfnWlanReasonCodeToString(wlrc, dwSize, szBuffer, NULL);
::MsiRecordSetStringW(hRecordProg, 3, m_sValue ); sReason.ReleaseBuffer(dwSize);
::MsiRecordSetStringW(hRecordProg, 4, sReason ); if (dwResult != NO_ERROR) sReason.Format(L"0x%x", wlrc);
::MsiRecordSetInteger(hRecordProg, 5, dwError );
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_WLAN_PROFILE_SET);
::MsiRecordSetStringW(hRecordProg, 2, sGUID );
::MsiRecordSetStringW(hRecordProg, 3, m_sValue );
::MsiRecordSetStringW(hRecordProg, 4, sReason );
::MsiRecordSetInteger(hRecordProg, 5, dwError );
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError);
}
} else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(1);
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_WLAN_NOT_INSTALLED);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError); return E_NOTIMPL;
} }
} }

View File

@ -33,3 +33,13 @@
#include <mstask.h> #include <mstask.h>
#include <taskschd.h> #include <taskschd.h>
#include <wlanapi.h> #include <wlanapi.h>
// Must not statically link to Wlanapi.dll as it is not available on Windows
// without a WLAN interface.
extern VOID (WINAPI *pfnWlanFreeMemory)(__in PVOID pMemory);
extern DWORD (WINAPI *pfnWlanOpenHandle)(__in DWORD dwClientVersion, __reserved PVOID pReserved, __out PDWORD pdwNegotiatedVersion, __out PHANDLE phClientHandle);
extern DWORD (WINAPI *pfnWlanCloseHandle)(__in HANDLE hClientHandle, __reserved PVOID pReserved);
extern DWORD (WINAPI *pfnWlanGetProfile)(__in HANDLE hClientHandle, __in CONST GUID *pInterfaceGuid, __in LPCWSTR strProfileName, __reserved PVOID pReserved, __deref_out LPWSTR *pstrProfileXml, __inout_opt DWORD *pdwFlags, __out_opt DWORD *pdwGrantedAccess);
extern DWORD (WINAPI *pfnWlanSetProfile)(__in HANDLE hClientHandle, __in CONST GUID *pInterfaceGuid, __in DWORD dwFlags, __in LPCWSTR strProfileXml, __in_opt LPCWSTR strAllUserProfileSecurity, __in BOOL bOverwrite, __reserved PVOID pReserved, __out DWORD *pdwReasonCode);
extern DWORD (WINAPI *pfnWlanDeleteProfile)(__in HANDLE hClientHandle, __in CONST GUID *pInterfaceGuid, __in LPCWSTR strProfileName, __reserved PVOID pReserved);
extern DWORD (WINAPI *pfnWlanReasonCodeToString)(__in DWORD dwReasonCode, __in DWORD dwBufferSize, __in_ecount(dwBufferSize) PWCHAR pStringBuffer, __reserved PVOID pReserved);