WTS_CONNECTSTATE_CLASS enumeration class - c++

I have to determine what state the user session is in. i.e if the the user is logged on and active or if the user is not logged on. To do this im using the function WTSEnumerateSessions and then I am checking the WTS_SESSION_INFOwhich is return from this function which has a state member.
According to the online documentation.
WTSActive A user is logged on to the WinStation
WTSDisconnected
The WinStation is active but the client is disconnected.
The problem is that im currently logged onto my system but the state returned for my current session is WTSDisconnected im expecting the state to be WTSActive is there any reason as to why this is happening?
Code below
PWTS_SESSION_INFO pSessionInfo(nullptr);
DWORD countOfSessions(0);
DWORD sessionIndex(0);
if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, // local machine
0, // reserved, must be zero
1, // Version, must be one
&pSessionInfo,
&countOfSessions) == FALSE)
{
return false;
}
if (countOfSessions == 0 || !pSessionInfo)
{
return false;
}
const DWORD currentSession = GetRealSessionID(CurrentSession); //This case we are in session 0
for (; sessionIndex < countOfSessions; ++sessionIndex)
{
WTS_SESSION_INFO& sessionInfo = pSessionInfo[sessionIndex];
if (currentSession == sessionInfo.SessionId)
{
if (sessionInfo.State == WTSActive)
{
return true;
}
}
}
return false;
Thanks

This doesn't make much sense. The most likely explanation is that currentSession is being assigned a value of 0, which is the session ID for the non-interactive isolated session in which services run.

Related

How to use sync token on Google People API

I cannot really find an example on how to use this.
Right now, I'm doing like this:
// Request 10 connections.
ListConnectionsResponse response = peopleService.people().connections()
.list("people/me")
.setRequestSyncToken(true)
.setPageSize(10)
.setPersonFields("names,emailAddresses")
.execute();
I make some changes to my contacts (adding, removing, updating), then I do this:
// Request 10 connections.
ListConnectionsResponse response2 = peopleService.people().connections()
.list("people/me")
.setSyncToken(response.getNextSyncToken())
.setPageSize(10)
.setPersonFields("names,emailAddresses")
.execute();
But it seems like I cannot get the changes I've done earlier, not even if I do them directly from the UI. I'm pretty sure I'm using the sync token in the wrong way.
Update (19/02/2020): In this example I call the API requesting the sync token in the first request (I successfully get the contacts), pause the execution (by breakpoint), delete a contact and update another one (from the web page), resume the execution and then I call the API again with the sync token that I extracted from the previous call. The result is that no change was made for some reason:
// Build a new authorized API client service.
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
PeopleService peopleService = new PeopleService.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
.setApplicationName(APPLICATION_NAME)
.build();
// Request 10 connections.
ListConnectionsResponse response = peopleService.people().connections()
.list("people/me")
.setPageSize(10)
.setPersonFields("names,emailAddresses")
.setRequestSyncToken(true)
.execute();
// Print display name of connections if available.
List<Person> connections = response.getConnections();
if (connections != null && connections.size() > 0) {
for (Person person : connections) {
List<Name> names = person.getNames();
if (names != null && names.size() > 0) {
System.out.println("Name: " + person.getNames().get(0)
.getDisplayName());
} else {
System.out.println("No names available for connection.");
}
}
} else {
System.out.println("No connections found.");
}
// CORRECT: 2 CONTACTS PRINTED
// CORRECT: THE SYNC TOKEN IS THERE
String syncToken = response.getNextSyncToken();
System.out.println("syncToken = "+syncToken);
// I SETUP A BREAKPOINT BELOW, I DELETE ONE CONTACT AND EDIT ANOTHER AND THEN I RESUME THE EXECUTING
// Request 10 connections.
response = peopleService.people().connections()
.list("people/me")
.setPageSize(10)
.setPersonFields("names,emailAddresses")
.setSyncToken(syncToken)
.execute();
// Print display name of connections if available.
connections = response.getConnections();
if (connections != null && connections.size() > 0) {
for (Person person : connections) {
List<Name> names = person.getNames();
if (names != null && names.size() > 0) {
System.out.println("Name: " + person.getNames().get(0)
.getDisplayName());
} else {
System.out.println("No names available for connection.");
}
}
} else {
System.out.println("No connections found.");
}
// WRONG: I GET "NO CONNECTIONS FOUND"
Something I've found out is that, when requesting or setting a sync token, you must iterate the entirety of the contacts for the nextSyncToken to be populated.
That means that as long as there is a nextPageToken (wink wink setPageSize(10)), the sync token will not be populated.
You could either:
A) Loop over all the contacts using your current
pagination, doing whatever you need to do at every
iteration, and after the last call retrieve the populated
sync token.
B) Iterate over all the contacts in one go, using the max
page size of 2000 and a single personField, retrieve the
token, and then do whatever you need to do. Note that if
you are expecting a user to have more than 2000
contacts, you will still need to call the next pages using
the nextPageToken.
Here is an exemple of a sync loop, adapted from Synchronize Resources Efficiently. Note that I usually use the Python client, so this Java code might not be 100% error free:
private static void run() throws IOException {
Request request = people_service.people().connections()
.list("people/me")
.setPageSize(10)
.setPersonFields("names,emailAddresses");
// Load the sync token stored from the last execution, if any.
// The syncSettingsDataStore is whatever you use for storage.
String syncToken = syncSettingsDataStore.get(SYNC_TOKEN_KEY);
String syncType = null;
// Perform the appropiate sync
if (syncToken == null) {
// Perform a full sync
request.setRequestSyncToken(true);
syncType = "FULL";
} else {
// Try to perform an incremental sync.
request.setSyncToken(syncToken);
syncType = "INCREMENTAL";
}
String pageToken = null;
ListConnectionsResponse response = null;
List<Person> contacts = null;
// Iterate over all the contacts, page by page.
do {
request.setPageToken(pageToken);
try {
response = request.execute();
} catch (GoogleJsonResponseException e) {
if (e.getStatusCode() == 410) {
// A 410 status code, "Gone", indicates that the sync token is
// invalid/expired.
// WARNING: The code is 400 in the Python client. I think the
// Java client uses the correct code, but be on the lookout.
// Clear the sync token.
syncSettingsDataStore.delete(SYNC_TOKEN_KEY);
// And anything else you need before re-syncing.
dataStore.clear();
// Restart
run();
} else {
throw e;
}
}
contacts = response.getItems();
if (contacts.size() == 0) {
System.out.println("No contacts to sync.");
} else if (syncType == "FULL"){
//do full sync for this page.
} else if (syncType == "INCREMENTAL") {
//do incremental sync for this page.
} else {
// What are you doing here???
}
pageToken = response.getNextPageToken();
} while (pageToken != null);
// Store the sync token from the last request for use at the next execution.
syncSettingsDataStore.set(SYNC_TOKEN_KEY, response.getNextSyncToken());
System.out.println("Sync complete.");
}

get current Logged in user name from within a C++ windows service

I have a service (written in C++), running under Windows 10. I need to get the name of the currently logged in user, but most Windows APIs I have found return the username of the calling thread, which when run as a system, is always "SYSTEM".
My use case is below:
Install the service with Administrator account
Log off from administrator
Login as a Non-Admin user
Query the service to get the current logged user name
You need to enumerate all sessions and identify the active session using WTSEnumerateSessions. Then you can query username of the active session using WTSQuerySessionInformation and query class WTSUsername.
WTS_SESSION_INFO *SessionInfo;
unsigned long SessionCount;
unsigned long ActiveSessionId = -1;
std::cout<<"Active Console Session Id : "<<WTSGetActiveConsoleSessionId()<<"\n";
if(WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &SessionInfo, &SessionCount))
{
for (auto i = 0; i < SessionCount; i++)
{
if (SessionInfo[i].State == WTSActive)
{
ActiveSessionId = SessionInfo[i].SessionId;
break;
}
}
char *UserName;
if (ActiveSessionId != -1)
{
unsigned long BytesReturned;
if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, ActiveSessionId, WTSUserName, &UserName, &BytesReturned))
{
std::cout<<UserName;
WTSFreeMemory(UserName);
}
}
WTSFreeMemory(SessionInfo);
}
Note that this will only work if there is only one active session (unlike terminal servers)
in addition to answer above, the following line
if (SessionInfo[i].State == WTSActive)
should be changed to
if (SessionInfo[i].State == WTSActive || SessionInfo[i].State == WTSConnected)
to include remote session too

Obtaining wi-fi connection status from Connection Manager

I have some code which successfully iterates over a list of wi-fi networks, and provides feedback about available networks. The essential calls shown here...
WlanOpenHandle(WLAN_API_VERSION, NULL, &dwVersion, &hSession);
PWLAN_INTERFACE_INFO_LIST pInterfaceInfoList = NULL;
WlanEnumInterfaces(hSession, NULL, &pInterfaceInfoList);
for(int i ...)
{
PWLAN_AVAILABLE_NETWORK_LIST pAvailableNetworkList = NULL;
WlanGetAvailableNetworkList(hSession, &interfaceGUID,
WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES |
WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES,
NULL, &pAvailableNetworkList);
for(int j ...)
{
WLAN_AVAILABLE_NETWORK network = pAvailableNetworkList->Network[j];
:
}
}
This all works fine, and inside the inner loop I'm able to access all of the attributes that I need, such as signal strength, security flags, etc via the network data structure.
One thing that I am not able to obtain is information regarding connection status, such as AUTHENTICATING or AUTHENTICATION_FAILED, etc, so I have tried to introduce another call inside the loop as follows...
CM_CONNECTION_DETAILS connectionDetails;
memset(&connectionDetails, 0, sizeof(CM_CONNECTION_DETAILS));
connectionDetails.Version = CM_CURRENT_VERSION;
const char* ccp = reinterpret_cast<const char*>(network.dot11Ssid.ucSSID);
mbstowcs(connectionDetails.szName, &ccp[0], network.dot11Ssid.uSSIDLength);
DWORD dwCount = sizeof(CM_CONNECTION_DETAILS);
CM_RESULT cmr = CmGetConnectionDetailsByName(connectionDetails.szName,
&connectionDetails, &dwCount);
if (cmr == CMRE_SUCCESS)
{
:
}
Upon calling the CmGetConnectionDetailsByName() function, the details inside the CM_CONNECTION_DETAILS structure look correct (name and version), but the function returns with CMRE_INVALID_CONNECTION and the structure is not populated.
I haven't been able to find any examples of this call being successful (only a couple of references to the call returning the same CMRE_INVALID_CONNECTION code).
Does anyone have any experience of using the call successfully, or alternatively suggest a better way to find out the connection status of a network (ie if AUTHENTICATION is in progress or if AUTHENTICATION failed, etc)?
[I'm using Visual Studio 2013 C++ (native Windows app, not MFC), the target is 32-bit and Unicode, running on Windows Compact 2013]
The function below doesn't quite give me the fine control that I was looking for, but it does at least give me the opportunity to find out the state a particular interface. This means that I can find out if the interface is currently in the process or authenticating, and depending whether the final state is connected or disconnected, I can find out if authentication was successful or not.
WLAN_INTERFACE_STATE getNetworkState(HANDLE hSession, GUID* pGUID, std::wstring& wsState, bool bReportState=true)
{
WLAN_INTERFACE_STATE result = wlan_interface_state_not_ready;
DWORD dwDataSize;
void* pData;
DWORD dwErrorCode = WlanQueryInterface(hSession, pGUID, wlan_intf_opcode_interface_state, NULL, &dwDataSize, &pData, NULL);
if (dwErrorCode == ERROR_SUCCESS && pData != NULL)
{
WLAN_INTERFACE_STATE* pState = reinterpret_cast<WLAN_INTERFACE_STATE*>(pData);
if (pState != NULL)
{
switch (*pState)
{
case wlan_interface_state_not_ready: wsState = L"NOT_READY"; break;
case wlan_interface_state_connected: wsState = L"CONNECTED"; break;
case wlan_interface_state_ad_hoc_network_formed: wsState = L"AD_HOC_NETWORK_FORMED"; break;
case wlan_interface_state_disconnecting: wsState = L"DISCONNECTING"; break;
case wlan_interface_state_disconnected: wsState = L"DISCONNECTED"; break;
case wlan_interface_state_associating: wsState = L"ASSOCIATING"; break;
case wlan_interface_state_discovering: wsState = L"DISCOVERING"; break;
case wlan_interface_state_authenticating: wsState = L"AUTHENTICATING"; break;
}
result = *pState;
}
WlanFreeMemory(pData);
}
return result;
}
A limitation of this check, is that it doesn't readily support multiple connections on the same interface, This query doesn't allow us to query to which of the connections the status refers.
If I arrive at a better solution, I will report it here.

Query cached ACL of a directory for a disconnected Windows domain user via Authz API

I would like to explore the effective rights of a local directory for the currently logged on domain user. This link has given me a good starting point and works as expected.
Unfortunately, querying the ACL fails when I disconnect from the domain controller and log on with my cached domain user profile. When being confronted with this environment, the AuthzInitializeContextFromSid function in the example code returns FALSE and sets 1355 (ERROR_NO_SUCH_DOMAIN) as the last error code:
...
PSID pSid = NULL;
BOOL bResult = FALSE;
LUID unusedId = { 0 };
AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext = NULL;
pSid = ConvertNameToBinarySid(lpszUserName);
if (pSid != NULL)
{
bResult = AuthzInitializeContextFromSid(0,
pSid,
hManager,
NULL,
unusedId,
NULL,
&hAuthzClientContext);
if (bResult)
{
GetAccess(hAuthzClientContext, psd);
AuthzFreeContext(hAuthzClientContext);
}
else
{
//prints 1355 as last error code
wprintf_s(_T("AuthzInitializeContextFromSid failed with %d\n"), GetLastError());
}
...
}
Is it possible to query the (cached) ACL nonetheless? Surely they must be accessible some way or another, even if the domain controller is unreachable.

How do I get the Service Display name in C++?

I am trying to get the display name of the running service using c++. I was trying to use the GetServiceDisplayName function but it does not seem to be working, not sure why.
TTServiceBegin( const char *svcName, PFNSERVICE pfnService, bool *svc, PFNTERMINATE pfnTerm,
int flags, int argc, char *argv[], DWORD dynamiteThreadWaitTime )
{
SC_HANDLE serviceStatusHandle;
DWORD dwSizeNeeded = 0 ;
TCHAR* szKeyName = NULL ;
serviceStatusHandle=OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE ,SC_MANAGER_ALL_ACCESS);
GetServiceDisplayName(serviceStatusHandle,svcName, NULL, &dwSizeNeeded);
if(dwSizeNeeded)
{
szKeyName = new char[dwSizeNeeded+1];
ZeroMemory(szKeyName,dwSizeNeeded+1);
if(GetServiceDisplayName(serviceStatusHandle ,svcName,szKeyName,&dwSizeNeeded)!=0)
{
MessageBox(0,szKeyName,"Got the key name",0);
}
}
When i run this code, i can never see the value of szKeyName in my debugger and it goes into the if block for the message box but never displays the message box. Not sure why?
Anyway to get this to work to get the display name of the service or any other/easier way to accomplish that task?
You need to use the WTSSendMessage instead of the MessageBox to interact with the active session.
WTS_SESSION_INFO* pSessionInfo = NULL;
DWORD dwSessionsCount = 0;
if(WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwSessionsCount))
{
for(int i=0; i<(int)dwSessionsCount; i++)
{
WTS_SESSION_INFO &si = pSessionInfo[i];
if(si.State == WTSActive)
{
DWORD dwIdCurrentSession = si.SessionId;
std::string strTitle = "Hello";
std::string strMessage = "This is a message from the service";
DWORD dwMsgBoxRetValue = 0;
if(WTSSendMessage(
WTS_CURRENT_SERVER_HANDLE,
dwIdCurrentSession,
(char*)strTitle.c_str(),
strTitle.size(),
(char*)strMessage.c_str(),
strMessage.size(),
MB_RETRYCANCEL | MB_ICONINFORMATION | MB_TOPMOST,
60000,
&dwMsgBoxRetValue,
TRUE))
{
switch(dwMsgBoxRetValue)
{
case IDTIMEOUT:
// Deal with TimeOut...
break;
case IDCANCEL:
// Deal With Cancel....
break;
}
}
else
{
// Deal With Error
}
break;
}
}
WTSFreeMemory(pSessionInfo);
}
The message box will not be visible on Windows Vista and later due to a change that has services running in a separate session (Session 0 Isolation) that does not have access to a desktop so the message box would not be visible to you, the logged on user.
On Window XP and earlier, you need to tick the Allow service to interact with desktop checkbox under the Log On tab in the service's properties dialog for your service to make message box appear.
Instead, you could write the service name out to a file or run a user application that accepts the name of the service to query and have it query and display the service name (I just tried with the posted code and it works correctly, displaying the message box).