DWORD VmAfdLocalGetMachineID( PWSTR* ppwszMachineID ) { DWORD dwError = 0; UINT32 apiType = VMAFD_IPC_GET_MACHINE_ID; DWORD noOfArgsIn = 0; DWORD noOfArgsOut = 0; PWSTR pwszMachineID = NULL; VMW_TYPE_SPEC output_spec[] = GET_MACHINE_ID_OUTPUT_PARAMS; noOfArgsOut = sizeof (output_spec) / sizeof (output_spec[0]); dwError = VecsLocalIPCRequest( apiType, noOfArgsIn, noOfArgsOut, NULL, output_spec); BAIL_ON_VMAFD_ERROR(dwError); dwError = *(output_spec[0].data.pUint32); BAIL_ON_VMAFD_ERROR(dwError); if (IsNullOrEmptyString(output_spec[1].data.pWString)) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMAFD_ERROR(dwError); } dwError = VmAfdAllocateStringW( output_spec[1].data.pWString, &pwszMachineID ); BAIL_ON_VMAFD_ERROR (dwError); *ppwszMachineID = pwszMachineID; cleanup: VmAfdFreeTypeSpecContent(output_spec, noOfArgsOut); return dwError; error: VmAfdLog(VMAFD_DEBUG_ANY, "VmAfdLocalGetMachineID failed. Error(%u)", dwError); goto cleanup; }
DWORD VmAfdLocalGetDomainName( PWSTR* ppwszDomain ) { DWORD dwError = 0; UINT32 apiType = VMAFD_IPC_GET_DOMAIN_NAME; DWORD noOfArgsIn = 0; DWORD noOfArgsOut = 0; PWSTR pwszDomain = NULL; VMW_TYPE_SPEC output_spec[] = GET_DOMAIN_NAME_OUTPUT_PARAMS; noOfArgsOut = sizeof (output_spec) / sizeof (output_spec[0]); dwError = VecsLocalIPCRequest( apiType, noOfArgsIn, noOfArgsOut, NULL, output_spec); BAIL_ON_VMAFD_ERROR(dwError); dwError = *(output_spec[0].data.pUint32); BAIL_ON_VMAFD_ERROR(dwError); if (IsNullOrEmptyString(output_spec[1].data.pWString)) { dwError = ERROR_NO_DATA; BAIL_ON_VMAFD_ERROR(dwError); } dwError = VmAfdAllocateStringW( output_spec[1].data.pWString, &pwszDomain ); BAIL_ON_VMAFD_ERROR (dwError); *ppwszDomain = pwszDomain; cleanup: VmAfdFreeTypeSpecContent(output_spec, noOfArgsOut); return dwError; error: VmAfdLog(VMAFD_DEBUG_ANY, "VmAfdLocalGetDomainName failed. Error(%u)", dwError); goto cleanup; }
DWORD VmAfdAllocateNameFromContextImpl ( PVM_AFD_SECURITY_CONTEXT pSecurityContext, PWSTR *ppszAccountName ) { DWORD dwError = 0; PWSTR pszAccountName = NULL; WCHAR wszEveryone[] = GROUP_EVERYONE_W; if (pSecurityContext->uid == EVERYONE_UID) { dwError = VmAfdAllocateStringW( wszEveryone, &pszAccountName ); BAIL_ON_VMAFD_ERROR (dwError); } else { struct passwd *pd = NULL; pd = getpwuid(pSecurityContext->uid); if (pd) { dwError = VmAfdAllocateStringWFromA( pd->pw_name, &pszAccountName ); BAIL_ON_VMAFD_ERROR (dwError); } } *ppszAccountName = pszAccountName; cleanup: return dwError ; error: if (ppszAccountName) { *ppszAccountName = NULL; } VMAFD_SAFE_FREE_MEMORY (pszAccountName); goto cleanup; }
static DWORD VmAfdGetHeartbeatInfo( PVMAFD_HB_INFO_W *ppHeartbeatInfoArr, PDWORD pdwEntriesCount, PBOOL pbNodeIsAlive ) { DWORD dwError = 0; DWORD dwEntriesCount = 0; PVMAFD_HB_INFO_W pHeartbeatInfoArr = NULL; BOOL bNodeIsAlive = TRUE; BOOL bServiceIsAlive = FALSE; DWORD dwEntriesIndex = 0; if (!ppHeartbeatInfoArr || !pdwEntriesCount || !pbNodeIsAlive) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMAFD_ERROR(dwError); } dwEntriesCount = gHeartbeatTable.dwNextAvailableIndex; if (dwEntriesCount) { DWORD dwIndex = 0; dwError = VmAfdAllocateMemory( sizeof(VMAFD_HB_INFO_W)*dwEntriesCount, (PVOID*)&pHeartbeatInfoArr ); BAIL_ON_VMAFD_ERROR(dwError); for ( dwIndex = 0; dwIndex < dwEntriesCount; ++dwIndex ) { PVMAFD_HB_NODE pCurrentNode = gHeartbeatTable.pEntries[dwIndex]; PVMAFD_HB_INFO_W pCurrentEntry = &pHeartbeatInfoArr[dwEntriesIndex]; if (pCurrentNode) { dwError = VmAfdAllocateStringW( pCurrentNode->pszServiceName, &pCurrentEntry->pszServiceName ); BAIL_ON_VMAFD_ERROR(dwError); bServiceIsAlive = VmAfdCheckServiceStatus(pCurrentNode); bNodeIsAlive = bNodeIsAlive && bServiceIsAlive; pCurrentEntry->bIsAlive = bServiceIsAlive? TRUE: FALSE; pCurrentEntry->dwLastHeartbeat = (DWORD)pCurrentNode->tLastPing; pCurrentEntry->dwPort = pCurrentNode->dwPort; ++dwEntriesIndex; } } } *pdwEntriesCount = dwEntriesIndex; *ppHeartbeatInfoArr = pHeartbeatInfoArr; *pbNodeIsAlive = bNodeIsAlive; cleanup: return dwError; error: if (ppHeartbeatInfoArr) { *ppHeartbeatInfoArr = NULL; } if (pdwEntriesCount) { *pdwEntriesCount = 0; } if (pbNodeIsAlive) { *pbNodeIsAlive = FALSE; } if (pHeartbeatInfoArr) { VmAfdFreeHbInfoArrayW(pHeartbeatInfoArr,dwEntriesCount); } goto cleanup; }
static DWORD VmAfdInsertNode( PCWSTR pwszServiceName, DWORD dwPort, PVMAFD_HB_NODE *ppNode ) { DWORD dwError = 0; PVMAFD_HB_NODE pNode = NULL; BOOL bIsHoldingLock = FALSE; if (IsNullOrEmptyString(pwszServiceName) || !ppNode ) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMAFD_ERROR(dwError); } dwError = VmAfdAllocateMemory( sizeof(VMAFD_HB_NODE), (PVOID *)&pNode ); BAIL_ON_VMAFD_ERROR(dwError); dwError = VmAfdAllocateStringW( pwszServiceName, &pNode->pszServiceName ); BAIL_ON_VMAFD_ERROR(dwError); pNode->dwPort = dwPort; *ppNode = pNode; VMAFD_LOCK_MUTEX_EXCLUSIVE(&rwlockHeartbeatTable, bIsHoldingLock); if (gHeartbeatTable.dwNextAvailableIndex == VMAFD_HEARTBEAT_TABLE_COUNT) { dwError = ERROR_OUTOFMEMORY; BAIL_ON_VMAFD_ERROR(dwError); } gHeartbeatTable.pEntries[gHeartbeatTable.dwNextAvailableIndex] = pNode; VmAfdUpdateAvailableIndex(); VMAFD_LOCK_MUTEX_UNLOCK(&rwlockHeartbeatTable, bIsHoldingLock); cleanup: VMAFD_LOCK_MUTEX_UNLOCK(&rwlockHeartbeatTable, bIsHoldingLock); return dwError; error: if (ppNode) { *ppNode = NULL; } if (pNode) { VmAfdFreeHbNode(pNode); } goto cleanup; }
DWORD VmAfdLocalGetMachineAccountInfo( PWSTR* ppwszAccount, PWSTR* ppwszPassword ) { DWORD dwError = 0; UINT32 apiType = VMAFD_IPC_GET_MACHINE_ACCOUNT_INFO; DWORD noOfArgsIn = 0; DWORD noOfArgsOut = 0; PWSTR pwszAccount= NULL; PWSTR pwszPassword = NULL; VMW_TYPE_SPEC output_spec[] = GET_MACHINE_ACCOUNT_INFO_OUTPUT_PARAMS; noOfArgsOut = sizeof (output_spec) / sizeof (output_spec[0]); dwError = VecsLocalIPCRequest( apiType, noOfArgsIn, noOfArgsOut, NULL, output_spec); BAIL_ON_VMAFD_ERROR(dwError); dwError = *(output_spec[0].data.pUint32); BAIL_ON_VMAFD_ERROR(dwError); if (IsNullOrEmptyString(output_spec[1].data.pWString)) { dwError = ERROR_NO_DATA; BAIL_ON_VMAFD_ERROR (dwError); } dwError = VmAfdAllocateStringW( output_spec[1].data.pWString, &pwszAccount ); BAIL_ON_VMAFD_ERROR (dwError); if (!output_spec[2].data.pWString) { dwError = ERROR_NO_DATA; BAIL_ON_VMAFD_ERROR (dwError); } dwError = VmAfdAllocateStringW( output_spec[2].data.pWString, &pwszPassword ); BAIL_ON_VMAFD_ERROR (dwError); *ppwszAccount = pwszAccount; *ppwszPassword = pwszPassword; cleanup: VmAfdFreeTypeSpecContent(output_spec, noOfArgsOut); return dwError; error: VmAfdLog(VMAFD_DEBUG_ANY, "VmAfdLocalGetMachineAccountInfo failed. Error(%u)", dwError); goto cleanup; }
static DWORD CdcUpdateCache( BOOL bPurgeRefresh ) { DWORD dwError = 0; PWSTR *ppszDomainControllers = NULL; DWORD dwDCCount = 0; DWORD dwIndex = 0; time_t timeTaken = 0; DWORD dwPingResult = 0; PCDC_DB_ENTRY_W pCdcEntry = NULL; if (bPurgeRefresh) { dwError = CdcGetDomainControllers( &ppszDomainControllers, &dwDCCount ); } if (!bPurgeRefresh || dwError) { dwError = CdcDbEnumDCEntries( &ppszDomainControllers, &dwDCCount ); BAIL_ON_VMAFD_ERROR(dwError); } if (dwDCCount) { dwError = VmAfdAllocateMemory( sizeof(CDC_DB_ENTRY_W)*dwDCCount, (PVOID *)&pCdcEntry ); BAIL_ON_VMAFD_ERROR(dwError); for (; dwIndex < dwDCCount; ++dwIndex) { dwError = VmAfdAllocateStringW( ppszDomainControllers[dwIndex], &pCdcEntry[dwIndex].pszDCName ); BAIL_ON_VMAFD_ERROR(dwError); dwError = CdcDCPing( ppszDomainControllers[dwIndex], NULL, //to accomodate multiple domains in future &dwPingResult, &timeTaken, &pCdcEntry[dwIndex].pszSiteName ); pCdcEntry[dwIndex].dwPingTime = (DWORD) (timeTaken); if (!dwPingResult) { pCdcEntry[dwIndex].bIsAlive = TRUE; } pCdcEntry[dwIndex].dwLastPing = (DWORD)time(NULL); pCdcEntry[dwIndex].cdcEntryStatus = bPurgeRefresh?CDC_DB_ENTRY_STATUS_NEW: CDC_DB_ENTRY_STATUS_UPDATE; } dwError = CdcRefreshCache(bPurgeRefresh, pCdcEntry, dwDCCount); BAIL_ON_VMAFD_ERROR(dwError); } cleanup: if (pCdcEntry) { VmAfdFreeCdcDbEntryArrayW(pCdcEntry,dwDCCount); } if (ppszDomainControllers) { VmAfdFreeStringArrayW( ppszDomainControllers, dwDCCount ); } return dwError; error: goto cleanup; }
DWORD VmAfdLocalQueryAD( PWSTR *ppwszComputer, PWSTR *ppwszDomain, PWSTR *ppwszDistinguishedName, PWSTR *ppwszNetbiosName ) { DWORD dwError = 0; UINT32 apiType = VMAFD_IPC_QUERY_AD; DWORD noOfArgsIn = 0; DWORD noOfArgsOut = 0; PWSTR pwszComputer = NULL; PWSTR pwszDomain = NULL; PWSTR pwszDistinguishedName = NULL; PWSTR pwszNetbiosName = NULL; VMW_TYPE_SPEC output_spec[] = QUERY_AD_OUTPUT_PARAMS; noOfArgsOut = sizeof (output_spec) / sizeof (output_spec[0]); dwError = VecsLocalIPCRequest( apiType, noOfArgsIn, noOfArgsOut, NULL, output_spec); BAIL_ON_VMAFD_ERROR(dwError); dwError = *(output_spec[0].data.pUint32); BAIL_ON_VMAFD_ERROR(dwError); if (IsNullOrEmptyString(output_spec[1].data.pWString)) { dwError = ERROR_NO_DATA; BAIL_ON_VMAFD_ERROR(dwError); } dwError = VmAfdAllocateStringW( output_spec[1].data.pWString, &pwszComputer ); BAIL_ON_VMAFD_ERROR (dwError); if (IsNullOrEmptyString(output_spec[2].data.pWString)) { dwError = ERROR_NO_DATA; BAIL_ON_VMAFD_ERROR(dwError); } dwError = VmAfdAllocateStringW( output_spec[2].data.pWString, &pwszDomain ); BAIL_ON_VMAFD_ERROR (dwError); if (ppwszDistinguishedName && !IsNullOrEmptyString(output_spec[3].data.pWString)) { dwError = VmAfdAllocateStringW( output_spec[3].data.pWString, &pwszDistinguishedName ); BAIL_ON_VMAFD_ERROR (dwError); } if (ppwszNetbiosName && !IsNullOrEmptyString(output_spec[4].data.pWString)) { dwError = VmAfdAllocateStringW( output_spec[4].data.pWString, &pwszNetbiosName ); BAIL_ON_VMAFD_ERROR (dwError); } *ppwszComputer = pwszComputer; *ppwszDomain = pwszDomain; if (ppwszDistinguishedName) { *ppwszDistinguishedName = pwszDistinguishedName; } if (ppwszNetbiosName) { *ppwszNetbiosName = pwszNetbiosName; } cleanup: VmAfdFreeTypeSpecContent(output_spec, noOfArgsOut); return dwError; error: VmAfdLog(VMAFD_DEBUG_ANY, "VmAfdLocalQueryAD failed. Error(%u)", dwError); goto cleanup; }
static DWORD CdcRefreshCache( BOOL bPurgeRefresh, PCDC_DB_ENTRY_W pCdcEntry, DWORD dwCount ) { //TODO: Or simply always purge and repopulate? DWORD dwError = 0; PWSTR *ppszDomainControllers = NULL; DWORD dwDBDCCount = 0; DWORD dwDbIndex = 0; DWORD dwIndex = 0; PWSTR pwszDomainName = NULL; if (!pCdcEntry) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMAFD_ERROR(dwError); } dwError = VmAfSrvGetDomainName(&pwszDomainName); BAIL_ON_VMAFD_ERROR(dwError); if (bPurgeRefresh) { dwError = CdcDbEnumDCEntries(&ppszDomainControllers, &dwDBDCCount); BAIL_ON_VMAFD_ERROR(dwError); for (; dwDbIndex<dwDBDCCount; ++dwDbIndex) { BOOL bFoundDC = FALSE; for (dwIndex = 0;dwIndex < dwCount; ++dwIndex) { if (VmAfdStringIsEqualW( ppszDomainControllers[dwDbIndex], pCdcEntry[dwIndex].pszDCName, FALSE ) ) { pCdcEntry[dwIndex].cdcEntryStatus = CDC_DB_ENTRY_STATUS_UPDATE; bFoundDC = TRUE; break; } } if (!bFoundDC) { CdcDbDeleteDCEntry(ppszDomainControllers[dwDbIndex]); } } } for (dwIndex = 0; dwIndex < dwCount; ++dwIndex) { dwError = VmAfdAllocateStringW( pwszDomainName, &pCdcEntry[dwIndex].pszDomainName ); BAIL_ON_VMAFD_ERROR(dwError); switch (pCdcEntry[dwIndex].cdcEntryStatus) { case CDC_DB_ENTRY_STATUS_NEW: dwError = CdcDbAddDCEntry(&pCdcEntry[dwIndex]); break; case CDC_DB_ENTRY_STATUS_UPDATE: dwError = CdcDbUpdateDCEntry(&pCdcEntry[dwIndex]); break; default: dwError = ERROR_INVALID_PARAMETER; break; } BAIL_ON_VMAFD_ERROR(dwError); } cleanup: if (ppszDomainControllers) { VmAfdFreeStringArrayW(ppszDomainControllers, dwDBDCCount); } VMAFD_SAFE_FREE_MEMORY(pwszDomainName); return dwError; error: goto cleanup; }
static DWORD CdcDCPing( PWSTR pszDCName, PWSTR pszDomainName, PDWORD pdwResult, time_t *ptimeTaken, PWSTR *ppszSiteName ) { DWORD dwError = 0; DWORD dwAfdPingResult = 0; DWORD dwDirPingResult = 0; time_t timeBefore = 0; time_t timeAfter = 0; time_t timeDiff = 0; PWSTR pwszAccount = NULL; PWSTR pwszPassword = NULL; PWSTR pwszAccountDN = NULL; PWSTR pwszDomain = NULL; PSTR pszSiteName = NULL; PWSTR pwszSiteName = NULL; PVMDIR_CONNECTION pConnection = NULL; BOOL bDCIsAlive = FALSE; if (!pszDCName || !pdwResult || !ptimeTaken || !ppszSiteName) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMAFD_ERROR(dwError); } dwError = VmAfSrvGetMachineAccountInfo( &pwszAccount, &pwszPassword, &pwszAccountDN, NULL ); BAIL_ON_VMAFD_ERROR(dwError); if (IsNullOrEmptyString(pszDomainName)) { dwError = VmAfSrvGetDomainName(&pwszDomain); BAIL_ON_VMAFD_ERROR(dwError); } else { dwError = VmAfdAllocateStringW( pszDomainName, &pwszDomain); BAIL_ON_VMAFD_ERROR(dwError); } time(&timeBefore); dwAfdPingResult = CdcVmafdHeartbeatPing( pszDCName, pwszAccount, pwszPassword, pwszDomain, &bDCIsAlive ); time(&timeAfter); timeDiff = timeAfter-timeBefore; dwDirPingResult = VmAfSrvDirOpenConnection( pszDCName, pwszDomain, pwszAccount, pwszPassword, &pConnection ); if (!dwDirPingResult) { dwDirPingResult = VmDirGetSiteName(pConnection,&pszSiteName); } if (dwDirPingResult) { *ppszSiteName = NULL; } else { dwError = VmAfdAllocateStringWFromA( pszSiteName, &pwszSiteName ); BAIL_ON_VMAFD_ERROR(dwError); *ppszSiteName = pwszSiteName; pwszSiteName = NULL; } *ptimeTaken = timeDiff; *pdwResult = !(!dwDirPingResult && !dwAfdPingResult && bDCIsAlive); cleanup: if (pConnection) { VmDirConnectionClose(pConnection); } VMAFD_SAFE_FREE_MEMORY(pwszDomain); VMAFD_SAFE_FREE_MEMORY(pwszAccount); VMAFD_SAFE_FREE_MEMORY(pwszPassword); VMAFD_SAFE_FREE_MEMORY(pwszAccountDN); VMAFD_SAFE_FREE_MEMORY(pwszSiteName); VMAFD_SAFE_FREE_MEMORY(pszSiteName); return dwError; error: if (ptimeTaken) { *ptimeTaken = 0; } if (ppszSiteName) { *ppszSiteName = NULL; } if (pdwResult) { *pdwResult = 0; } goto cleanup; }
{ DWORD dwError = 0; PCDC_DC_INFO_W pAffinitizedDC = NULL; PWSTR pwszDCName = NULL; if (!ppwszDCName) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMAFD_ERROR(dwError) } dwError = CdcSrvGetDCName(NULL, &pAffinitizedDC); BAIL_ON_VMAFD_ERROR(dwError); dwError = VmAfdAllocateStringW( pAffinitizedDC->pszDCName, &pwszDCName ); BAIL_ON_VMAFD_ERROR(dwError); *ppwszDCName = pwszDCName; cleanup: if (pAffinitizedDC) { VmAfdFreeDomainControllerInfoW(pAffinitizedDC); } return dwError; error: if (ppwszDCName)
DWORD CdcSrvGetDCStatusInfo( PWSTR pwszDCName, PWSTR pwszDomainName, PCDC_DC_STATUS_INFO_W *ppCdcStatusInfo, PVMAFD_HB_STATUS_W *ppHeartbeatStatus ) { DWORD dwError = 0; PWSTR pwszDomainToUse = NULL; PCDC_DC_STATUS_INFO_W pCdcStatusInfo = NULL; PVMAFD_HB_STATUS_W pHeartbeatStatus = NULL; if (IsNullOrEmptyString(pwszDCName)) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMAFD_ERROR(dwError); } if (!ppCdcStatusInfo) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMAFD_ERROR(dwError); } if (IsNullOrEmptyString(pwszDomainName)) { dwError = VmAfSrvGetDomainName(&pwszDomainToUse); BAIL_ON_VMAFD_ERROR(dwError); } else { dwError = VmAfdAllocateStringW(pwszDomainName, &pwszDomainToUse); BAIL_ON_VMAFD_ERROR(dwError); } dwError = CdcDbGetDCInfo( pwszDCName, pwszDomainToUse, &pCdcStatusInfo ); BAIL_ON_VMAFD_ERROR(dwError); if (ppHeartbeatStatus) { dwError = CdcDbGetHeartbeatStatus( pwszDCName, pwszDomainToUse, &pHeartbeatStatus ); BAIL_ON_VMAFD_ERROR(dwError); pHeartbeatStatus->bIsAlive = pCdcStatusInfo->bIsAlive; *ppHeartbeatStatus = pHeartbeatStatus; } *ppCdcStatusInfo = pCdcStatusInfo; cleanup: VMAFD_SAFE_FREE_MEMORY(pwszDomainToUse); return dwError; error: if (ppCdcStatusInfo) { *ppCdcStatusInfo = NULL; } if (ppHeartbeatStatus) { *ppHeartbeatStatus = NULL; } if (pCdcStatusInfo) { VmAfdFreeCdcStatusInfoW(pCdcStatusInfo); } if (pHeartbeatStatus) { VmAfdFreeHbStatusW(pHeartbeatStatus); } goto cleanup; }
DWORD CdcSrvEnumDCEntries( PWSTR **pppszEntryNames, PDWORD pdwCount ) { DWORD dwError = 0; DWORD dwCount = 0; DWORD dwIndex = 0; PWSTR* ppszEntryNames = NULL; PCDC_DB_ENTRY_W pCdcEntries = NULL; UINT64 iStart = 0; UINT64 iEnd = 0; if (!pppszEntryNames || !pdwCount) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMAFD_ERROR(dwError); } iStart = VmAfdGetTimeInMilliSec(); dwError = CdcDbEnumDCEntries(&pCdcEntries, &dwCount); BAIL_ON_VMAFD_ERROR(dwError); if (dwCount) { dwError = VmAfdAllocateMemory( sizeof(PWSTR)*dwCount, (PVOID)&ppszEntryNames ); BAIL_ON_VMAFD_ERROR(dwError); for (; dwIndex < dwCount; ++dwIndex) { dwError = VmAfdAllocateStringW( pCdcEntries[dwIndex].pszDCName, &ppszEntryNames[dwIndex] ); BAIL_ON_VMAFD_ERROR(dwError); } } iEnd = VmAfdGetTimeInMilliSec(); *pppszEntryNames = ppszEntryNames; *pdwCount = dwCount; cleanup: if (pCdcEntries) { VmAfdFreeCdcDbEntriesW(pCdcEntries, dwCount); } return dwError; error: (DWORD)VmAfdAddDBSuperLogEntry( gVmafdGlobals.pLogger, iStart, iEnd, pCdcEntries, dwError); if (pppszEntryNames) { *pppszEntryNames = NULL; } if (ppszEntryNames) { VmAfdFreeStringArrayW(ppszEntryNames, dwCount); } goto cleanup; }