#include #include "ErrCtrl.h" #include "Utils.h" #include "ArgParse.h" //---------------------------------------------------- // Utility function for parsing an UINT type of argument; DWORD FnPaUint(LPWSTR *pwszArg, WCHAR wchTerm, UINT *pnValue) { DWORD dwErr = ERROR_SUCCESS; UINT nValue = 0; LPWSTR wszArg = (*pwszArg); if (*wszArg == L'\0' || *wszArg == wchTerm) dwErr = ERROR_BAD_FORMAT; else { for (nValue = 0; *wszArg != L'\0' && iswdigit(*wszArg); wszArg++) { if (*wszArg == wchTerm) break; nValue = nValue * 10 + ((*wszArg) - L'0'); } if (*wszArg != wchTerm) dwErr = ERROR_BAD_FORMAT; else if (pnValue != NULL) *pnValue = nValue; } *pwszArg = wszArg; SetLastError(dwErr); return dwErr; } //---------------------------------------------------- // Utility function for parsing two hexa digits (one byte) DWORD FnPaByte(LPWSTR *pwszArg, BYTE *pbtValue) { DWORD dwErr = ERROR_SUCCESS; BYTE btValue = 0; LPWSTR wszArg = (*pwszArg); if (iswxdigit(*wszArg)) { btValue = HEX(*wszArg); wszArg++; } else dwErr = ERROR_BAD_FORMAT; if (dwErr == ERROR_SUCCESS && iswxdigit(*wszArg)) { btValue <<= 4; btValue |= HEX(*wszArg); wszArg++; } else dwErr = ERROR_BAD_FORMAT; if (dwErr == ERROR_SUCCESS && pbtValue != NULL) *pbtValue = btValue; *pwszArg = wszArg; SetLastError(dwErr); return dwErr; } //---------------------------------------------------- // Utility function for common postprocessing of argument parsing routines DWORD FnPaPostProcess(DWORD dwErr, PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry) { if (dwErr == ERROR_SUCCESS) { // it is guaranteed that when parsing the argument of a parameter // the parameter itself is encountered for the first time. Consequently // there is no need for checking whether this argumented param ever occured before. pPDData->dwArgumentedParams |= pPDEntry->nParamID; } SetLastError(dwErr); return dwErr; } //---------------------------------------------------- // Parser for the Guid type of argument DWORD FnPaGuid(PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry, LPWSTR wszParamArg) { DWORD dwErr = ERROR_SUCCESS; LPWSTR wszGuid = NULL; UINT nGuidLen = wcslen(wszParamArg); if (nGuidLen < 1) dwErr = ERROR_BAD_FORMAT; if (dwErr == ERROR_SUCCESS) { // create a buffer for the GUID wszGuid = MemCAlloc((nGuidLen + 1) * sizeof(WCHAR)); if (wszGuid == NULL) dwErr = GetLastError(); } if (dwErr == ERROR_SUCCESS) { wcscpy(wszGuid, wszParamArg); MemFree(pPDData->wzcIntfEntry.wszGuid); // copy the GUID into the param descriptors data pPDData->wzcIntfEntry.wszGuid = wszGuid; } return FnPaPostProcess(dwErr, pPDData, pPDEntry); } //---------------------------------------------------- // Parser for the argument of the "mask" parameter DWORD FnPaMask(PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry, LPWSTR wszParamArg) { DWORD dwErr = ERROR_SUCCESS; NDIS_802_11_NETWORK_INFRASTRUCTURE ndIm; dwErr = FnPaUint(&wszParamArg, L'\0', (UINT *)&ndIm); if (dwErr == ERROR_SUCCESS) { if (ndIm > Ndis802_11AutoUnknown) dwErr = ERROR_INVALID_DATA; else { pPDData->wzcIntfEntry.dwCtlFlags &= ~INTFCTL_CM_MASK; pPDData->wzcIntfEntry.dwCtlFlags |= ndIm; } } return FnPaPostProcess(dwErr, pPDData, pPDEntry); } //---------------------------------------------------- // Parser for the argument of the "enabled" parameter DWORD FnPaEnabled(PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry, LPWSTR wszParamArg) { DWORD dwErr = ERROR_SUCCESS; BOOL bEnabled; dwErr = FnPaUint(&wszParamArg, L'\0', (UINT *)&bEnabled); if (dwErr == ERROR_SUCCESS) { if (bEnabled > 1) dwErr = ERROR_INVALID_DATA; else if (bEnabled) pPDData->wzcIntfEntry.dwCtlFlags |= INTFCTL_ENABLED; else pPDData->wzcIntfEntry.dwCtlFlags &= ~INTFCTL_ENABLED; } return FnPaPostProcess(dwErr, pPDData, pPDEntry); } //---------------------------------------------------- // Parser for the argument of the "ssid" parameter DWORD FnPaSsid(PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry, LPWSTR wszParamArg) { DWORD dwErr = ERROR_SUCCESS; UINT nSsidWLen = wcslen(wszParamArg); UINT nSsidALen; LPBYTE pbtSsid = NULL; // ssid is hardcoded to 32 bytes in ntddndis.h pbtSsid = MemCAlloc(33); if (pbtSsid == NULL) dwErr = GetLastError(); // trim out the '"' if any if (dwErr == ERROR_SUCCESS && nSsidWLen > 2 && wszParamArg[0] == L'"' && wszParamArg[nSsidWLen-1] == '"') { wszParamArg++; nSsidWLen-=2; wszParamArg[nSsidWLen+1] = L'\0'; } if (dwErr == ERROR_SUCCESS) { nSsidALen = WideCharToMultiByte( CP_ACP, 0, wszParamArg, wcslen(wszParamArg)+1, pbtSsid, 33, NULL, NULL); // the call above includes the '\0' in the count of // characters converted. Normalize the length then, // (failure => all "f"s which is higher than 32 hence error) nSsidALen--; // a valid SSID should contain at least 1 char, and no more than 32 if (nSsidALen < 1 || nSsidALen > 32) dwErr = ERROR_INVALID_DATA; } if (dwErr == ERROR_SUCCESS) { pPDData->wzcIntfEntry.rdSSID.dwDataLen = nSsidALen; pPDData->wzcIntfEntry.rdSSID.pData = pbtSsid; } else MemFree(pbtSsid); return FnPaPostProcess(dwErr, pPDData, pPDEntry); } //---------------------------------------------------- // Parser for the argument of the "bssid" parameter DWORD FnPaBssid(PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry, LPWSTR wszParamArg) { DWORD dwErr = ERROR_SUCCESS; PNDIS_802_11_MAC_ADDRESS pndMac = NULL; UINT i; // allocate space for the mac address pndMac = MemCAlloc(sizeof(NDIS_802_11_MAC_ADDRESS)); if (pndMac == NULL) dwErr = GetLastError(); for (i = 0; dwErr == ERROR_SUCCESS && i < sizeof(NDIS_802_11_MAC_ADDRESS); i++) { dwErr = FnPaByte(&wszParamArg, &((*pndMac)[i])); if (dwErr == ERROR_SUCCESS) { if (i != sizeof(NDIS_802_11_MAC_ADDRESS)-1 && *wszParamArg == L':') wszParamArg++; else if (i != sizeof(NDIS_802_11_MAC_ADDRESS)-1 || *wszParamArg != L'\0') dwErr = ERROR_BAD_FORMAT; } } if (dwErr == ERROR_SUCCESS) { pPDData->wzcIntfEntry.rdBSSID.dwDataLen = sizeof(NDIS_802_11_MAC_ADDRESS); pPDData->wzcIntfEntry.rdBSSID.pData = (LPBYTE)pndMac; } else { MemFree(pndMac); } return FnPaPostProcess(dwErr, pPDData, pPDEntry); } //---------------------------------------------------- // Parser for the argument of the "im" parameter DWORD FnPaIm(PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry, LPWSTR wszParamArg) { DWORD dwErr = ERROR_SUCCESS; NDIS_802_11_NETWORK_INFRASTRUCTURE ndIm; dwErr = FnPaUint(&wszParamArg, L'\0', (UINT *)&ndIm); if (dwErr == ERROR_SUCCESS) { if (ndIm > Ndis802_11Infrastructure) dwErr = ERROR_INVALID_DATA; else pPDData->wzcIntfEntry.nInfraMode = ndIm; } return FnPaPostProcess(dwErr, pPDData, pPDEntry); } //---------------------------------------------------- // Parser for the argument of the "am" parameter DWORD FnPaAm(PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry, LPWSTR wszParamArg) { DWORD dwErr = ERROR_SUCCESS; NDIS_802_11_AUTHENTICATION_MODE ndAm; dwErr = FnPaUint(&wszParamArg, L'\0', (UINT *)&ndAm); if (dwErr == ERROR_SUCCESS) { if (ndAm > Ndis802_11AuthModeShared) dwErr = ERROR_INVALID_DATA; else pPDData->wzcIntfEntry.nAuthMode = ndAm; } return FnPaPostProcess(dwErr, pPDData, pPDEntry); } //---------------------------------------------------- // Parser for the argument of the "priv" parameter DWORD FnPaPriv(PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry, LPWSTR wszParamArg) { DWORD dwErr = ERROR_SUCCESS; NDIS_802_11_WEP_STATUS ndEncr; dwErr = FnPaUint(&wszParamArg, L'\0', (UINT *)&ndEncr); if (dwErr == ERROR_SUCCESS) { if (ndEncr != Ndis802_11WEPDisabled && ndEncr != Ndis802_11WEPEnabled) dwErr = ERROR_INVALID_DATA; else { // change the semantic of nWepStatus according to XP SP (which expects a boolean!) pPDData->wzcIntfEntry.nWepStatus = ndEncr == Ndis802_11WEPDisabled ? 0 : 1; } } return FnPaPostProcess(dwErr, pPDData, pPDEntry); } //---------------------------------------------------- // Parser for the argument of the "key" parameter DWORD FnPaKey(PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry, LPWSTR wszParamArg) { DWORD dwErr = ERROR_SUCCESS; UINT nKIdx, nKLen; BOOL bIsHex; PNDIS_802_11_WEP pndKey = NULL; // get the key index dwErr = FnPaUint(&wszParamArg, L':', &nKIdx); // check whether the key index is within permitted values if (dwErr == ERROR_SUCCESS && (nKIdx < 1 || nKIdx > 4)) dwErr = ERROR_INVALID_DATA; // check the key material length if (dwErr == ERROR_SUCCESS) { wszParamArg++; nKLen = wcslen(wszParamArg); // trim out the '"' if any if (nKLen > 2 && wszParamArg[0] == L'"' && wszParamArg[nKLen-1] == '"') { wszParamArg++; nKLen-=2; } switch (nKLen) { case 10: // 5 bytes = 40 bits case 26: // 13 bytes = 104 bits case 32: // 16 bytes = 128 bits nKLen >>= 1; bIsHex = TRUE; break; case 5: // 5 bytes = 40 bits case 13: // 13 bytes = 104 bits case 16: // 16 bytes = 128 bits bIsHex = FALSE; break; default: dwErr = ERROR_BAD_LENGTH; break; } } // allocate space for the key material if (dwErr == ERROR_SUCCESS) { pndKey = MemCAlloc(FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial) + nKLen); if (pndKey == NULL) dwErr = GetLastError(); else { pndKey->Length = FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial) + nKLen; pndKey->KeyIndex = nKIdx-1; pndKey->KeyLength = nKLen; } } // parse the key material and fill it in the allocated space if (dwErr == ERROR_SUCCESS) { if (bIsHex) { UINT i; for (i = 0; dwErr == ERROR_SUCCESS && i < pndKey->KeyLength; i++) dwErr = FnPaByte(&wszParamArg, &(pndKey->KeyMaterial[i])); } else { UINT nAnsi; nAnsi = WideCharToMultiByte( CP_ACP, 0, wszParamArg, nKLen, pndKey->KeyMaterial, pndKey->KeyLength, NULL, NULL); if (nAnsi != pndKey->KeyLength) dwErr = ERROR_BAD_FORMAT; else wszParamArg += pndKey->KeyLength; } } // if the key material proved to be correct, then pass the data in the pPDData if (dwErr == ERROR_SUCCESS) { _Asrt(*wszParamArg == L'\0' || *wszParamArg == L'"', L"Code bug - key length incorrectly inferred.\n"); pPDData->wzcIntfEntry.rdCtrlData.dwDataLen = pndKey->Length; pPDData->wzcIntfEntry.rdCtrlData.pData = (LPBYTE)pndKey; } else { MemFree(pndKey); } return FnPaPostProcess(dwErr, pPDData, pPDEntry);; } //---------------------------------------------------- // Parser for the boolean argument for the "onex" parameter DWORD FnPaOneX(PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry, LPWSTR wszParamArg) { DWORD dwErr = ERROR_SUCCESS; BOOL bOneX; dwErr = FnPaUint(&wszParamArg, L'\0', (UINT *)&bOneX); if (dwErr == ERROR_SUCCESS) { if (bOneX != TRUE && bOneX != FALSE) dwErr = ERROR_INVALID_DATA; else { // save the parameter's argument pPDData->bOneX = bOneX; } } return FnPaPostProcess(dwErr, pPDData, pPDEntry); } //---------------------------------------------------- // Parser for the "outfile" file name parameter FnPaOutFile(PPARAM_DESCR_DATA pPDData, PPARAM_DESCR pPDEntry, LPWSTR wszParamArg) { FILE *pfOut; DWORD dwErr = ERROR_SUCCESS; pfOut = _wfopen(wszParamArg, L"a+"); if (pfOut == NULL) dwErr = GetLastError(); if (dwErr == ERROR_SUCCESS) { CHAR szCrtDate[32]; CHAR szCrtTime[32]; pPDData->pfOut = pfOut; fprintf(pPDData->pfOut,"\n\n[%s - %s]\n", _strdate(szCrtDate), _strtime(szCrtTime)); } return FnPaPostProcess(dwErr, pPDData, pPDEntry); }