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 609 by douglas, 2005-11-30T21:55:40-08:00 vs.
Revision 619 by douglas, 2005-12-13T02:27:26-08:00

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines