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 613 by douglas, 2005-12-12T18:30:01-08:00

# Line 6 | Line 6
6  
7   #include <windows.h>
8   #include <tchar.h>
9 + #include <signal.h>
10 + #include <wtsapi32.h>
11  
12 < /*LPTSTR name;
12 > #include <iostream>
13 > #include <string>
14 > #include <sstream>
15 > #include <vector>
16 > #include <set>
17 >
18 > inline std::string Utf8(const std::wstring &wstring)
19 > {
20 >        std::string string(::WideCharToMultiByte(CP_UTF8, 0, wstring.data(), int(wstring.size()), NULL, 0, NULL, NULL), '\0');
21 >
22 >        ::WideCharToMultiByte(CP_UTF8, 0, wstring.data(), int(wstring.size()), const_cast<LPSTR>(string.data()), int(string.size()), NULL, NULL);
23 >
24 >        return string;
25 > }
26 >
27 > class Finger
28 > {
29 > private:
30 >        struct Login
31 >        {
32 >                std::string login, name, session;
33 >                Login(const std::string &login, const std::string &session) : login(login), session(session)
34 >                {
35 >                }
36 >                bool operator<(const Login &login) const
37 >                {
38 >                        if (this->login == login.login)
39 >                                return session < login.session;
40 >                        else
41 >                                return this->login < login.login;
42 >                }
43 >        };
44 >        std::ostringstream stream;
45 >        std::set<Login> logins;
46 >
47 > public:
48 >        Finger(bool full)
49 >        {
50 >                PWTS_SESSION_INFO sessions;
51 >                DWORD count;
52 >
53 >                ::WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessions, &count);
54 >
55 >                for (PWTS_SESSION_INFO session(sessions); session != sessions + count; ++session)
56 >                {
57 >                        LPTSTR name;
58 >                        DWORD size;
59 >
60 >                        ::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSUserName, &name, &size);
61 >
62 >                        if (!std::wstring(name).empty())
63 >                        {
64 >                                LPTSTR session_;
65 >
66 >                                ::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSWinStationName, &session_, &size);
67 >
68 >                                Login login(Utf8(name), Utf8(session_));
69 >
70 >                                ::WTSFreeMemory(session_);
71 >
72 >                                logins.insert(login);
73 >                        }
74 >
75 >                        ::WTSFreeMemory(name);
76 >                }
77 >
78 >                ::WTSFreeMemory(sessions);
79 >
80 >                if (!full)
81 >                {
82 >                        stream << "Login\t\tName" << std::string(17, ' ') << "Session\r\n";
83 >
84 >                        for (std::set<Login>::const_iterator login(logins.begin()); login != logins.end(); ++login)
85 >                                stream << login->login << std::string(16 - login->login.size(), ' ') << login->name << std::string(21 - login->name.size(), ' ') << login->session << "\r\n";
86 >                }
87 >        }
88 >
89 >        Finger(const std::string &name)
90 >        {
91 >                //NetQueryDisplayInformation
92 >                //NetUserGetInfo
93 >        }
94 >
95 >        inline operator std::string()
96 >        {
97 >                return stream.str();
98 >        }
99 > };
100 >
101 > LPTSTR name;
102   SERVICE_STATUS status;
103   SERVICE_STATUS_HANDLE handle;
104 < HANDLE stop;*/
104 > HANDLE stop;
105   WSADATA data;
106 + std::vector<HANDLE> threads;
107  
108 < /*void WINAPI FingerMain(DWORD argc, LPTSTR *argv);
109 < void WINAPI FingerControl(DWORD control);*/
108 > void FingerDaemon();
109 > DWORD WINAPI FingerListen(LPVOID server_);
110 > DWORD WINAPI FingerDo(LPVOID client_);
111 > void FingerStop(int);
112 > void WINAPI FingerMain(DWORD argc, LPTSTR *argv);
113 > void WINAPI FingerControl(DWORD control);
114  
115   int _tmain(int argc, TCHAR *argv[])
116   {
117 <        /*SERVICE_TABLE_ENTRY entry[] = { { TEXT("CCS Finger Daemon"), LPSERVICE_MAIN_FUNCTION(FingerMain) }, { NULL, NULL } };
117 >        SERVICE_TABLE_ENTRY entry[] = { { TEXT("CCS Finger Daemon"), LPSERVICE_MAIN_FUNCTION(FingerMain) }, { NULL, NULL } };
118  
119 <        if (!StartServiceCtrlDispatcher(entry))
119 >        if (!::StartServiceCtrlDispatcher(entry))
120          {
121 <                DWORD error(GetLastError());
121 >                DWORD error(::GetLastError());
122  
123                  switch (error)
124                  {
125                  case ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
126 <                        std::cerr << "ERROR_FAILED_SERVICE_CONTROLLER_CONNECT" << std::endl;
31 <
32 <                        break;
126 >                        goto go;
127  
128                  case ERROR_INVALID_DATA:
129                          std::cerr << "ERROR_INVALID_DATA" << std::endl;
# Line 49 | Line 143 | int _tmain(int argc, TCHAR *argv[])
143          }
144  
145          return 0;
52 }
146  
147 < void WINAPI FingerMain(DWORD argc, LPTSTR *argv)
148 < {
56 <        name = argv[0];
57 <        handle = RegisterServiceCtrlHandler(name, LPHANDLER_FUNCTION(FingerControl));
58 <        stop = CreateEvent(NULL, TRUE, FALSE, NULL);
147 > go:
148 >        stop = ::CreateEvent(NULL, TRUE, FALSE, NULL);
149  
150 <        //*/
150 >        ::signal(SIGINT, FingerStop);
151  
152 <        WSAStartup(MAKEWORD(2, 0), &data);
152 >        try
153 >        {
154 >                FingerDaemon();
155 >        }
156 >        catch (...) {}
157  
158 <        //
158 >        return 0;
159 > }
160  
161 <        /*status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
162 <        status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
163 <        status.dwServiceSpecificExitCode = 0;
69 <        status.dwCurrentState = SERVICE_RUNNING;
70 <        status.dwWin32ExitCode = NO_ERROR;
71 <        status.dwCheckPoint = 0;
72 <        status.dwWaitHint = 0;
161 > void FingerDaemon()
162 > {
163 >        ::WSAStartup(MAKEWORD(2, 0), &data);
164  
165 <        SetServiceStatus(handle, &status);*/
165 >        //
166  
167 <        SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
167 >        SOCKET server(::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP));
168          SOCKADDR_IN service;
169          
170          service.sin_family = AF_INET;
171          service.sin_addr.s_addr = inet_addr("0.0.0.0");
172          service.sin_port = htons(79);
173  
174 <        bind(sock, (SOCKADDR *)(&service), sizeof (service));
175 <        listen(sock, SOMAXCONN);
174 >        ::bind(server, (SOCKADDR *)(&service), sizeof (service));
175 >        ::listen(server, SOMAXCONN);
176 >
177 >        threads.push_back(::CreateThread(NULL, 0, FingerListen, &server, 0, NULL));
178 >
179 >        while(::WaitForSingleObject(stop, 1000) != WAIT_OBJECT_0);
180 >
181 >        //
182 >
183 >        ::closesocket(server);
184 >
185 >        ::WSACleanup();
186 > }
187 >
188 > DWORD WINAPI FingerListen(LPVOID server_)
189 > {
190 >        SOCKET &server(*reinterpret_cast<SOCKET *>(server_));
191  
192 <        //while(/*WaitForSingleObject(stop, 1000) != WAIT_OBJECT_0*/ /*&&*/)
192 >        while (true)
193          {
194 <                //
194 >                SOCKET client(accept(server, NULL, NULL));
195 >
196 >                threads.push_back(::CreateThread(NULL, 0, FingerDo, &client, 0, NULL));
197          }
198  
199 +        return 0;
200 + }
201 +
202 + DWORD WINAPI FingerDo(LPVOID client_)
203 + {
204 +        SOCKET &client(*reinterpret_cast<SOCKET *>(client_));
205 +        char buffer[1024];
206 +        std::istringstream stream(std::string(buffer, ::recv(client, buffer, sizeof buffer, 0)));
207 +        std::string line;
208 +
209 +        std::getline(stream, line);
210 +
211 +        stream.str(line);
212 +
213 +        std::getline(stream, line, '\r');
214 +
215 +        stream.str(line);
216 +
217 +        std::string name;
218 +        bool full(false);
219 +
220 +        while (stream >> line)
221 +                if (line == "/W")
222 +                        full = true;
223 +                else
224 +                        name = line;
225 +
226 +        std::string finger(name.empty() ? Finger(full) : Finger(name));
227 +
228 +        ::send(client, finger.data(), int(finger.size()), 0);
229 +        ::closesocket(client);
230 +
231 +        return 0;
232 + }
233 +
234 + void FingerStop(int)
235 + {
236 +        ::SetEvent(stop);
237 + }
238 +
239 + void WINAPI FingerMain(DWORD argc, LPTSTR *argv)
240 + {
241 +        name = argv[0];
242 +        handle = RegisterServiceCtrlHandler(name, LPHANDLER_FUNCTION(FingerControl));
243 +        stop = ::CreateEvent(NULL, TRUE, FALSE, NULL);
244 +
245          //
246  
247 <        WSACleanup();
247 >        status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
248 >        status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
249 >        status.dwServiceSpecificExitCode = 0;
250 >        status.dwCurrentState = SERVICE_RUNNING;
251 >        status.dwWin32ExitCode = NO_ERROR;
252 >        status.dwCheckPoint = 0;
253 >        status.dwWaitHint = 0;
254  
255 <        /*status.dwCurrentState = SERVICE_STOPPED;
255 >        ::SetServiceStatus(handle, &status);
256 >
257 >        try
258 >        {
259 >                FingerDaemon();
260 >        }
261 >        catch (...) {}
262 >
263 >        status.dwCurrentState = SERVICE_STOPPED;
264          status.dwWin32ExitCode = NO_ERROR;
265          status.dwCheckPoint = 0;
266          status.dwWaitHint = 0;
267  
268 <        SetServiceStatus(handle, &status);
268 >        ::SetServiceStatus(handle, &status);
269   }
270  
271   void WINAPI FingerControl(DWORD control)
# Line 108 | Line 276 | void WINAPI FingerControl(DWORD control)
276          case SERVICE_CONTROL_SHUTDOWN:
277                  status.dwCurrentState = SERVICE_STOP_PENDING;
278  
279 <                SetEvent(stop);
279 >                ::SetEvent(stop);
280  
281                  break;
282  
# Line 116 | Line 284 | void WINAPI FingerControl(DWORD control)
284                  break;
285          }
286  
287 <        SetServiceStatus(handle, &status);*/
120 <
121 <        return 0;
287 >        ::SetServiceStatus(handle, &status);
288   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines