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 608 by douglas, 2005-11-30T18:23:39-08:00 vs.
Revision 617 by douglas, 2005-12-13T01:35:20-08:00

# Line 8 | Line 8
8   #include <tchar.h>
9   #include <signal.h>
10   #include <wtsapi32.h>
11 + #include <lm.h>
12 + #include <shlobj.h>
13  
14 + #include <algorithm>
15   #include <iostream>
16 + #include <iomanip>
17   #include <string>
18 + #include <sstream>
19 + #include <vector>
20 + #include <map>
21 + #include <cwctype>
22  
23 < LPTSTR name;
24 < SERVICE_STATUS status;
25 < SERVICE_STATUS_HANDLE handle;
26 < HANDLE stop;
27 < WSADATA data;
23 > std::ostream &operator<<(std::ostream &out, WTS_CONNECTSTATE_CLASS status)
24 > {
25 >        switch (status)
26 >        {
27 >        case WTSActive:
28 >                return out << "Active";
29  
30 < void FingerDaemon();
31 < void FingerStop(int);
23 < void WINAPI FingerMain(DWORD argc, LPTSTR *argv);
24 < void WINAPI FingerControl(DWORD control);
30 >        case WTSConnected:
31 >                return out << "Connected";
32  
33 < int _tmain(int argc, TCHAR *argv[])
33 >        case WTSConnectQuery:
34 >                return out << "Connecting";
35 >
36 >        case WTSShadow:
37 >                return out << "Shadowing";
38 >
39 >        case WTSDisconnected:
40 >                return out << "Disconnected";
41 >
42 >        case WTSIdle:
43 >                return out << "Idle";
44 >
45 >        case WTSListen:
46 >                return out << "Listening";
47 >
48 >        case WTSReset:
49 >                return out << "Reseting";
50 >
51 >        case WTSDown:
52 >                return out << "Down";
53 >
54 >        case WTSInit:
55 >                return out << "Initializing";
56 >
57 >        default:
58 >                return out << "Unknown";
59 >        }
60 > }
61 >
62 > inline std::string Utf8(const std::wstring &wstring)
63   {
64 <        PWTS_SESSION_INFO sessions;
65 <        DWORD count;
64 >        std::string string(::WideCharToMultiByte(CP_UTF8, 0, wstring.data(), int(wstring.size()), NULL, 0, NULL, NULL), '\0');
65 >
66 >        ::WideCharToMultiByte(CP_UTF8, 0, wstring.data(), int(wstring.size()), const_cast<LPSTR>(string.data()), int(string.size()), NULL, NULL);
67 >
68 >        return string;
69 > }
70  
71 <        if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessions, &count))
71 > class Finger
72 > {
73 >        class Login
74          {
75 <                std::cerr << GetLastError() << std::endl;
75 >                std::wstring login;
76 >                mutable USER_INFO_11 *info;
77  
78 <                return 1;
79 <        }
78 >                inline void GetInfo() const
79 >                {
80 >                        if (!info)
81 >                                ::NetUserGetInfo(NULL, login.c_str(), 11, reinterpret_cast<LPBYTE *>(&info));
82 >                }
83 >        public:
84 >                std::string session;
85 >                DWORD id;
86 >                WTS_CONNECTSTATE_CLASS status;
87 >
88 >                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)
89 >                {
90 >                }
91 >
92 >                ~Login()
93 >                {
94 >                        if (!info)
95 >                                ::NetApiBufferFree(info);
96 >                }
97 >
98 >                std::string GetShortName() const
99 >                {
100 >                        GetInfo();
101 >
102 >                        return Utf8(std::wstring(info->usri11_full_name).substr(0, 20));
103 >                }
104 >
105 >                std::string GetName() const
106 >                {
107 >                        GetInfo();
108 >
109 >                        return Utf8(info->usri11_full_name);
110 >                }
111 >
112 >                std::string GetDirectory() const
113 >                {
114 >                        HANDLE token;
115 >
116 >                        if (::WTSQueryUserToken(id, &token))
117 >                        {
118 >                                TCHAR directory[MAX_PATH];
119 >
120 >                                ::SHGetFolderPath(NULL, CSIDL_PROFILE, token, SHGFP_TYPE_CURRENT, directory);
121 >                                ::CloseHandle(token);
122 >
123 >                                return Utf8(directory);
124 >                        }
125 >                        else
126 >                        {
127 >                                TCHAR directory_[MAX_PATH];
128  
129 <        for (PWTS_SESSION_INFO session = sessions; session != sessions + count; ++session)
129 >                                ::SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, directory_);
130 >
131 >                                std::wstring directory(directory_);
132 >
133 >                                directory.replace(directory.rfind('\\') + 1, std::wstring::npos, login);
134 >
135 >                                return Utf8(directory);
136 >                        }
137 >                }
138 >        };
139 >
140 >        std::ostringstream stream;
141 >        std::multimap<std::string, Login> logins;
142 >
143 >        void Full()
144          {
145 <                LPTSTR userName, clientName;
146 <                DWORD userNameSize, clientNameSize;
145 >                for (std::multimap<std::string, Login>::const_iterator login(logins.begin()); login != logins.end(); login = logins.upper_bound(login->first))
146 >                {
147 >                        stream << "Login: " << login->first << std::string(33 - login->first.size(), ' ') << "Name: " << login->second.GetName() << "\r\nDirectory: " << login->second.GetDirectory() << "\r\n";
148 >                }
149 >        }
150  
151 <                WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSUserName, &userName, &userNameSize);
152 <                WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSClientName, &clientName, &clientNameSize);
151 > public:
152 >        Finger(bool full)
153 >        {
154 >                PWTS_SESSION_INFO sessions;
155 >                DWORD count;
156  
157 <                std::wcout << '{' << std::endl
47 <                        << '\t' << session->SessionId << std::endl
48 <                        << '\t' << session->pWinStationName << std::endl
49 <                        << '\t';
157 >                ::WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessions, &count);
158  
159 <                switch (session->State)
159 >                for (PWTS_SESSION_INFO session(sessions); session != sessions + count; ++session)
160                  {
161 <                case WTSActive:
162 <                        std::cout << "Active";
55 <                        
56 <                        break;
57 <                case WTSConnected:
58 <                        std::cout << "Connected";
161 >                        LPTSTR name;
162 >                        DWORD size;
163  
164 <                        break;
61 <                case WTSConnectQuery:
62 <                        std::cout << "Connect Query";
164 >                        ::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSUserName, &name, &size);
165  
166 <                        break;
65 <                case WTSShadow:
66 <                        std::cout << "Shadow";
166 >                        std::wstring name_(name);
167  
168 <                        break;
69 <                case WTSDisconnected:
70 <                        std::cout << "Disconnected";
168 >                        ::WTSFreeMemory(name);
169  
170 <                        break;
171 <                case WTSIdle:
172 <                        std::cout << "Idle";
170 >                        if (!name_.empty())
171 >                        {
172 >                                std::transform(name_.begin(), name_.end(), name_.begin(), std::towlower);
173  
174 <                        break;
77 <                case WTSListen:
78 <                        std::cout << "Listen";
174 >                                LPTSTR session_;
175  
176 <                        break;
81 <                case WTSReset:
82 <                        std::cout << "Reset";
176 >                                ::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSWinStationName, &session_, &size);
177  
178 <                        break;
85 <                case WTSDown:
86 <                        std::cout << "Down";
178 >                                Login login(name_, session->SessionId, session_, session->State);
179  
180 <                        break;
89 <                case WTSInit:
90 <                        std::cout << "Init";
180 >                                ::WTSFreeMemory(session_);
181  
182 <                        break;
182 >                                logins.insert(std::make_pair(Utf8(name_), login));
183 >                        }
184                  }
185  
186 <                std::wcout << std::endl << '\t' << userName << std::endl
96 <                        << '\t' << clientName << std::endl
97 <                        << '}' << std::endl;
186 >                ::WTSFreeMemory(sessions);
187  
188 <                WTSFreeMemory(userName);
189 <                WTSFreeMemory(clientName);
188 >                if (!full)
189 >                {
190 >                        stream << "Login" << std::string(11, ' ') << "Name" << std::string(17, ' ') << "Id     Session       Status\r\n";
191 >
192 >                        for (std::multimap<std::string, Login>::const_iterator login(logins.begin()); login != logins.end(); ++login)
193 >                                stream << login->first << std::string(16 - login->first.size(), ' ') << login->second.GetShortName() << std::string(21 - login->second.GetShortName().size(), ' ') << std::setw(5) << std::left << login->second.id << "  " << login->second.session << std::string(14 - login->second.session.size(), ' ') << login->second.status << "\r\n";
194 >                }
195 >                else
196 >                        Full();
197          }
198  
199 <        WTSFreeMemory(sessions);
199 >        Finger(const std::string &name)
200 >        {
201 >                //NetQueryDisplayInformation
202 >                //NetUserGetInfo
203 >        }
204  
205 <        /*SERVICE_TABLE_ENTRY entry[] = { { TEXT("CCS Finger Daemon"), LPSERVICE_MAIN_FUNCTION(FingerMain) }, { NULL, NULL } };
205 >        inline operator std::string()
206 >        {
207 >                return stream.str();
208 >        }
209 > };
210 >
211 > LPTSTR name;
212 > SERVICE_STATUS status;
213 > SERVICE_STATUS_HANDLE handle;
214 > HANDLE stop;
215 > WSADATA data;
216 > std::vector<HANDLE> threads;
217  
218 <        if (!StartServiceCtrlDispatcher(entry))
218 > void FingerDaemon();
219 > DWORD WINAPI FingerListen(LPVOID server_);
220 > DWORD WINAPI FingerDo(LPVOID client_);
221 > void FingerStop(int);
222 > void WINAPI FingerMain(DWORD argc, LPTSTR *argv);
223 > void WINAPI FingerControl(DWORD control);
224 >
225 > int _tmain(int argc, TCHAR *argv[])
226 > {
227 >        SERVICE_TABLE_ENTRY entry[] = { { TEXT("CCSFinger"), LPSERVICE_MAIN_FUNCTION(FingerMain) }, { NULL, NULL } };
228 >
229 >        if (!::StartServiceCtrlDispatcher(entry))
230          {
231 <                DWORD error(GetLastError());
231 >                DWORD error(::GetLastError());
232  
233                  switch (error)
234                  {
# Line 133 | Line 255 | int _tmain(int argc, TCHAR *argv[])
255          return 0;
256  
257   go:
258 <        stop = CreateEvent(NULL, TRUE, FALSE, NULL);
258 >        for (int index(1); index != argc; ++index)
259 >        {
260 >                std::wstring arg(argv[index]);
261 >
262 >                if (arg == TEXT("create"))
263 >                {
264 >                        TCHAR file[MAX_PATH];
265 >
266 >                        ::GetModuleFileName(NULL, file, MAX_PATH);
267  
268 <        signal(SIGINT, FingerStop);
268 >                        SC_HANDLE manager(::OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CREATE_SERVICE)), service(::CreateService(manager, TEXT("CCSFinger"), TEXT("CCS Finger Daemon"), 0, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, file, NULL, NULL, TEXT("TermService\0"), NULL, TEXT("")));
269 >
270 >                        if (!service)
271 >                                std::cerr << ::GetLastError() << std::endl;
272 >                        else
273 >                                ::CloseServiceHandle(service);
274 >
275 >                        ::CloseServiceHandle(manager);
276 >
277 >                        return 0;
278 >                }
279 >                else if (arg == TEXT("delete"))
280 >                {
281 >                        SC_HANDLE manager(::OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, DELETE)), service(::OpenService(manager, TEXT("CCSFinger"), DELETE));
282 >
283 >                        if (!::DeleteService(service))
284 >                                std::cerr << ::GetLastError() << std::endl;
285 >
286 >                        ::CloseServiceHandle(service);
287 >                        ::CloseServiceHandle(manager);
288 >
289 >                        return 0;
290 >                }
291 >        }
292 >
293 >        stop = ::CreateEvent(NULL, TRUE, FALSE, NULL);
294 >
295 >        ::signal(SIGINT, FingerStop);
296  
297          try
298          {
# Line 143 | Line 300 | go:
300          }
301          catch (...) {}
302  
303 <        return 0;*/
303 >        return 0;
304   }
305  
306   void FingerDaemon()
307   {
308 <        WSAStartup(MAKEWORD(2, 0), &data);
308 >        ::WSAStartup(MAKEWORD(2, 0), &data);
309  
310          //
311  
312 <        SOCKET server(socket(PF_INET, SOCK_STREAM, IPPROTO_TCP));
312 >        SOCKET server(::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP));
313          SOCKADDR_IN service;
314          
315          service.sin_family = AF_INET;
316          service.sin_addr.s_addr = inet_addr("0.0.0.0");
317          service.sin_port = htons(79);
318  
319 <        bind(server, (SOCKADDR *)(&service), sizeof (service));
320 <        listen(server, SOMAXCONN);
319 >        ::bind(server, (SOCKADDR *)(&service), sizeof (service));
320 >        ::listen(server, SOMAXCONN);
321 >
322 >        threads.push_back(::CreateThread(NULL, 0, FingerListen, &server, 0, NULL));
323 >
324 >        while(::WaitForSingleObject(stop, 1000) != WAIT_OBJECT_0);
325 >
326 >        //
327 >
328 >        ::closesocket(server);
329 >
330 >        ::WSACleanup();
331 > }
332  
333 <        SOCKET client;
333 > DWORD WINAPI FingerListen(LPVOID server_)
334 > {
335 >        SOCKET &server(*reinterpret_cast<SOCKET *>(server_));
336  
337 <        while(WaitForSingleObject(stop, 1000) != WAIT_OBJECT_0 && (client = accept(server, NULL, NULL)) == SOCKET_ERROR)
337 >        while (true)
338          {
339 <                //
339 >                SOCKET client(accept(server, NULL, NULL));
340 >
341 >                threads.push_back(::CreateThread(NULL, 0, FingerDo, &client, 0, NULL));
342          }
343  
344 <        //
344 >        return 0;
345 > }
346 >
347 > DWORD WINAPI FingerDo(LPVOID client_)
348 > {
349 >        SOCKET &client(*reinterpret_cast<SOCKET *>(client_));
350 >        char buffer[1024];
351 >        std::istringstream stream(std::string(buffer, ::recv(client, buffer, sizeof buffer, 0)));
352 >        std::string line;
353 >
354 >        std::getline(stream, line);
355  
356 <        closesocket(server);
356 >        stream.str(line);
357  
358 <        WSACleanup();
358 >        std::getline(stream, line, '\r');
359 >
360 >        stream.str(line);
361 >
362 >        std::string name;
363 >        bool full(false);
364 >
365 >        while (stream >> line)
366 >                if (line == "/W")
367 >                        full = true;
368 >                else
369 >                        name = line;
370 >
371 >        std::string finger(name.empty() ? Finger(full) : Finger(name));
372 >
373 >        ::send(client, finger.data(), int(finger.size()), 0);
374 >        ::closesocket(client);
375 >
376 >        return 0;
377   }
378  
379   void FingerStop(int)
380   {
381 <        SetEvent(stop);
182 <
183 <        std::cout << "Stop!" << std::endl;
381 >        ::SetEvent(stop);
382   }
383  
384   void WINAPI FingerMain(DWORD argc, LPTSTR *argv)
385   {
386          name = argv[0];
387          handle = RegisterServiceCtrlHandler(name, LPHANDLER_FUNCTION(FingerControl));
388 <        stop = CreateEvent(NULL, TRUE, FALSE, NULL);
388 >        stop = ::CreateEvent(NULL, TRUE, FALSE, NULL);
389  
390          //
391  
# Line 199 | Line 397 | void WINAPI FingerMain(DWORD argc, LPTST
397          status.dwCheckPoint = 0;
398          status.dwWaitHint = 0;
399  
400 <        SetServiceStatus(handle, &status);
400 >        ::SetServiceStatus(handle, &status);
401  
402          try
403          {
# Line 212 | Line 410 | void WINAPI FingerMain(DWORD argc, LPTST
410          status.dwCheckPoint = 0;
411          status.dwWaitHint = 0;
412  
413 <        SetServiceStatus(handle, &status);
413 >        ::SetServiceStatus(handle, &status);
414   }
415  
416   void WINAPI FingerControl(DWORD control)
# Line 223 | Line 421 | void WINAPI FingerControl(DWORD control)
421          case SERVICE_CONTROL_SHUTDOWN:
422                  status.dwCurrentState = SERVICE_STOP_PENDING;
423  
424 <                SetEvent(stop);
424 >                ::SetEvent(stop);
425  
426                  break;
427  
# Line 231 | Line 429 | void WINAPI FingerControl(DWORD control)
429                  break;
430          }
431  
432 <        SetServiceStatus(handle, &status);
432 >        ::SetServiceStatus(handle, &status);
433   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines