ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/CCSFinger/CCSFinger.cpp
(Generate patch)

Comparing CCSFinger/CCSFinger.cpp (file contents):
Revision 594 by douglas, 2005-11-27T17:04:53-08:00 vs.
Revision 616 by douglas, 2005-12-12T20:25:45-08:00

# Line 6 | Line 6
6  
7   #include <windows.h>
8   #include <tchar.h>
9 + #include <signal.h>
10 + #include <wtsapi32.h>
11 + #include <lm.h>
12 +
13 + #include <algorithm>
14 + #include <iostream>
15 + #include <iomanip>
16 + #include <string>
17 + #include <sstream>
18 + #include <vector>
19 + #include <map>
20 + #include <cwctype>
21  
22 < /*LPTSTR name;
22 > std::ostream &operator<<(std::ostream &out, WTS_CONNECTSTATE_CLASS status)
23 > {
24 >        switch (status)
25 >        {
26 >        case WTSActive:
27 >                return out << "Active";
28 >
29 >        case WTSConnected:
30 >                return out << "Connected";
31 >
32 >        case WTSConnectQuery:
33 >                return out << "Connecting";
34 >
35 >        case WTSShadow:
36 >                return out << "Shadowing";
37 >
38 >        case WTSDisconnected:
39 >                return out << "Disconnected";
40 >
41 >        case WTSIdle:
42 >                return out << "Idle";
43 >
44 >        case WTSListen:
45 >                return out << "Listening";
46 >
47 >        case WTSReset:
48 >                return out << "Reseting";
49 >
50 >        case WTSDown:
51 >                return out << "Down";
52 >
53 >        case WTSInit:
54 >                return out << "Initializing";
55 >
56 >        default:
57 >                return out << "Unknown";
58 >        }
59 > }
60 >
61 > inline std::string Utf8(const std::wstring &wstring)
62 > {
63 >        std::string string(::WideCharToMultiByte(CP_UTF8, 0, wstring.data(), int(wstring.size()), NULL, 0, NULL, NULL), '\0');
64 >
65 >        ::WideCharToMultiByte(CP_UTF8, 0, wstring.data(), int(wstring.size()), const_cast<LPSTR>(string.data()), int(string.size()), NULL, NULL);
66 >
67 >        return string;
68 > }
69 >
70 > class Finger
71 > {
72 >        class Login
73 >        {
74 >                std::wstring login;
75 >                mutable USER_INFO_11 *info;
76 >
77 >                inline void GetInfo() const
78 >                {
79 >                        ::NetUserGetInfo(NULL, login.c_str(), 11, reinterpret_cast<LPBYTE *>(&info));
80 >                }
81 >        public:
82 >                std::string session;
83 >                DWORD id;
84 >                WTS_CONNECTSTATE_CLASS status;
85 >
86 >                Login(const std::wstring &login, DWORD id, const std::wstring &session, WTS_CONNECTSTATE_CLASS status) : login(login), info(NULL), id(id), session(Utf8(session)), status(status)
87 >                {
88 >                }
89 >
90 >                ~Login()
91 >                {
92 >                        if (!info)
93 >                                ::NetApiBufferFree(info);
94 >                }
95 >
96 >                std::string GetName() const
97 >                {
98 >                        if (!info)
99 >                                GetInfo();
100 >
101 >                        return Utf8(std::wstring(info->usri11_full_name).substr(0, 20));
102 >                }
103 >        };
104 >
105 >        std::ostringstream stream;
106 >        std::multimap<std::string, Login> logins;
107 >
108 >        void Full()
109 >        {
110 >                for (std::multimap<std::string, Login>::const_iterator login(logins.begin()); login != logins.end(); login = logins.upper_bound(login->first))
111 >                {
112 >                        stream << "Login: " << login->first << std::string(33 - login->first.size(), ' ') << "Name: " << login->second.GetName() << "\r\n";
113 >                }
114 >        }
115 >
116 > public:
117 >        Finger(bool full)
118 >        {
119 >                PWTS_SESSION_INFO sessions;
120 >                DWORD count;
121 >
122 >                ::WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessions, &count);
123 >
124 >                for (PWTS_SESSION_INFO session(sessions); session != sessions + count; ++session)
125 >                {
126 >                        LPTSTR name;
127 >                        DWORD size;
128 >
129 >                        ::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSUserName, &name, &size);
130 >
131 >                        std::wstring name_(name);
132 >
133 >                        ::WTSFreeMemory(name);
134 >
135 >                        if (!name_.empty())
136 >                        {
137 >                                std::transform(name_.begin(), name_.end(), name_.begin(), std::towlower);
138 >
139 >                                LPTSTR session_;
140 >
141 >                                ::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSWinStationName, &session_, &size);
142 >
143 >                                Login login(name_, session->SessionId, session_, session->State);
144 >
145 >                                ::WTSFreeMemory(session_);
146 >
147 >                                logins.insert(std::make_pair(Utf8(name_), login));
148 >                        }
149 >                }
150 >
151 >                ::WTSFreeMemory(sessions);
152 >
153 >                if (!full)
154 >                {
155 >                        stream << "Login" << std::string(11, ' ') << "Name" << std::string(17, ' ') << "Id     Session       Status\r\n";
156 >
157 >                        for (std::multimap<std::string, Login>::const_iterator login(logins.begin()); login != logins.end(); ++login)
158 >                                stream << login->first << std::string(16 - login->first.size(), ' ') << login->second.GetName() << std::string(21 - login->second.GetName().size(), ' ') << std::setw(5) << std::left << login->second.id << "  " << login->second.session << std::string(14 - login->second.session.size(), ' ') << login->second.status << "\r\n";
159 >                }
160 >                else
161 >                        Full();
162 >        }
163 >
164 >        Finger(const std::string &name)
165 >        {
166 >                //NetQueryDisplayInformation
167 >                //NetUserGetInfo
168 >        }
169 >
170 >        inline operator std::string()
171 >        {
172 >                return stream.str();
173 >        }
174 > };
175 >
176 > LPTSTR name;
177   SERVICE_STATUS status;
178   SERVICE_STATUS_HANDLE handle;
179 < HANDLE stop;*/
179 > HANDLE stop;
180   WSADATA data;
181 + std::vector<HANDLE> threads;
182  
183 < /*void WINAPI FingerMain(DWORD argc, LPTSTR *argv);
184 < void WINAPI FingerControl(DWORD control);*/
183 > void FingerDaemon();
184 > DWORD WINAPI FingerListen(LPVOID server_);
185 > DWORD WINAPI FingerDo(LPVOID client_);
186 > void FingerStop(int);
187 > void WINAPI FingerMain(DWORD argc, LPTSTR *argv);
188 > void WINAPI FingerControl(DWORD control);
189  
190   int _tmain(int argc, TCHAR *argv[])
191   {
192 <        /*SERVICE_TABLE_ENTRY entry[] = { { TEXT("CCS Finger Daemon"), LPSERVICE_MAIN_FUNCTION(FingerMain) }, { NULL, NULL } };
192 >        SERVICE_TABLE_ENTRY entry[] = { { TEXT("CCS Finger Daemon"), LPSERVICE_MAIN_FUNCTION(FingerMain) }, { NULL, NULL } };
193  
194 <        if (!StartServiceCtrlDispatcher(entry))
194 >        if (!::StartServiceCtrlDispatcher(entry))
195          {
196 <                DWORD error(GetLastError());
196 >                DWORD error(::GetLastError());
197  
198                  switch (error)
199                  {
200                  case ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
201 <                        std::cerr << "ERROR_FAILED_SERVICE_CONTROLLER_CONNECT" << std::endl;
31 <
32 <                        break;
201 >                        goto go;
202  
203                  case ERROR_INVALID_DATA:
204                          std::cerr << "ERROR_INVALID_DATA" << std::endl;
# Line 49 | Line 218 | int _tmain(int argc, TCHAR *argv[])
218          }
219  
220          return 0;
52 }
221  
222 < void WINAPI FingerMain(DWORD argc, LPTSTR *argv)
223 < {
56 <        name = argv[0];
57 <        handle = RegisterServiceCtrlHandler(name, LPHANDLER_FUNCTION(FingerControl));
58 <        stop = CreateEvent(NULL, TRUE, FALSE, NULL);
222 > go:
223 >        stop = ::CreateEvent(NULL, TRUE, FALSE, NULL);
224  
225 <        //*/
225 >        ::signal(SIGINT, FingerStop);
226  
227 <        WSAStartup(MAKEWORD(2, 0), &data);
227 >        try
228 >        {
229 >                FingerDaemon();
230 >        }
231 >        catch (...) {}
232  
233 <        //
233 >        return 0;
234 > }
235  
236 <        /*status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
237 <        status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
238 <        status.dwServiceSpecificExitCode = 0;
69 <        status.dwCurrentState = SERVICE_RUNNING;
70 <        status.dwWin32ExitCode = NO_ERROR;
71 <        status.dwCheckPoint = 0;
72 <        status.dwWaitHint = 0;
236 > void FingerDaemon()
237 > {
238 >        ::WSAStartup(MAKEWORD(2, 0), &data);
239  
240 <        SetServiceStatus(handle, &status);*/
240 >        //
241  
242 <        SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
242 >        SOCKET server(::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP));
243          SOCKADDR_IN service;
244          
245          service.sin_family = AF_INET;
246          service.sin_addr.s_addr = inet_addr("0.0.0.0");
247          service.sin_port = htons(79);
248  
249 <        bind(sock, (SOCKADDR *)(&service), sizeof (service));
250 <        listen(sock, SOMAXCONN);
249 >        ::bind(server, (SOCKADDR *)(&service), sizeof (service));
250 >        ::listen(server, SOMAXCONN);
251 >
252 >        threads.push_back(::CreateThread(NULL, 0, FingerListen, &server, 0, NULL));
253 >
254 >        while(::WaitForSingleObject(stop, 1000) != WAIT_OBJECT_0);
255 >
256 >        //
257 >
258 >        ::closesocket(server);
259  
260 <        //while(/*WaitForSingleObject(stop, 1000) != WAIT_OBJECT_0*/ /*&&*/)
260 >        ::WSACleanup();
261 > }
262 >
263 > DWORD WINAPI FingerListen(LPVOID server_)
264 > {
265 >        SOCKET &server(*reinterpret_cast<SOCKET *>(server_));
266 >
267 >        while (true)
268          {
269 <                //
269 >                SOCKET client(accept(server, NULL, NULL));
270 >
271 >                threads.push_back(::CreateThread(NULL, 0, FingerDo, &client, 0, NULL));
272          }
273  
274 +        return 0;
275 + }
276 +
277 + DWORD WINAPI FingerDo(LPVOID client_)
278 + {
279 +        SOCKET &client(*reinterpret_cast<SOCKET *>(client_));
280 +        char buffer[1024];
281 +        std::istringstream stream(std::string(buffer, ::recv(client, buffer, sizeof buffer, 0)));
282 +        std::string line;
283 +
284 +        std::getline(stream, line);
285 +
286 +        stream.str(line);
287 +
288 +        std::getline(stream, line, '\r');
289 +
290 +        stream.str(line);
291 +
292 +        std::string name;
293 +        bool full(false);
294 +
295 +        while (stream >> line)
296 +                if (line == "/W")
297 +                        full = true;
298 +                else
299 +                        name = line;
300 +
301 +        std::string finger(name.empty() ? Finger(full) : Finger(name));
302 +
303 +        ::send(client, finger.data(), int(finger.size()), 0);
304 +        ::closesocket(client);
305 +
306 +        return 0;
307 + }
308 +
309 + void FingerStop(int)
310 + {
311 +        ::SetEvent(stop);
312 + }
313 +
314 + void WINAPI FingerMain(DWORD argc, LPTSTR *argv)
315 + {
316 +        name = argv[0];
317 +        handle = RegisterServiceCtrlHandler(name, LPHANDLER_FUNCTION(FingerControl));
318 +        stop = ::CreateEvent(NULL, TRUE, FALSE, NULL);
319 +
320          //
321  
322 <        WSACleanup();
322 >        status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
323 >        status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
324 >        status.dwServiceSpecificExitCode = 0;
325 >        status.dwCurrentState = SERVICE_RUNNING;
326 >        status.dwWin32ExitCode = NO_ERROR;
327 >        status.dwCheckPoint = 0;
328 >        status.dwWaitHint = 0;
329 >
330 >        ::SetServiceStatus(handle, &status);
331 >
332 >        try
333 >        {
334 >                FingerDaemon();
335 >        }
336 >        catch (...) {}
337  
338 <        /*status.dwCurrentState = SERVICE_STOPPED;
338 >        status.dwCurrentState = SERVICE_STOPPED;
339          status.dwWin32ExitCode = NO_ERROR;
340          status.dwCheckPoint = 0;
341          status.dwWaitHint = 0;
342  
343 <        SetServiceStatus(handle, &status);
343 >        ::SetServiceStatus(handle, &status);
344   }
345  
346   void WINAPI FingerControl(DWORD control)
# Line 108 | Line 351 | void WINAPI FingerControl(DWORD control)
351          case SERVICE_CONTROL_SHUTDOWN:
352                  status.dwCurrentState = SERVICE_STOP_PENDING;
353  
354 <                SetEvent(stop);
354 >                ::SetEvent(stop);
355  
356                  break;
357  
# Line 116 | Line 359 | void WINAPI FingerControl(DWORD control)
359                  break;
360          }
361  
362 <        SetServiceStatus(handle, &status);*/
120 <
121 <        return 0;
362 >        ::SetServiceStatus(handle, &status);
363   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines