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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines