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 613 by douglas, 2005-12-12T18:30:01-08:00 vs.
Revision 618 by douglas, 2005-12-13T02:23:55-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 <string>
20 > #include <map>
21   #include <sstream>
22 + #include <string>
23   #include <vector>
24 < #include <set>
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   {
# Line 26 | Line 72 | inline std::string Utf8(const std::wstri
72  
73   class Finger
74   {
75 < private:
30 <        struct Login
75 >        class Login
76          {
77 <                std::string login, name, session;
78 <                Login(const std::string &login, const std::string &session) : login(login), session(session)
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 <                bool operator<(const Login &login) const
113 >
114 >                std::string GetDirectory() const
115                  {
116 <                        if (this->login == login.login)
117 <                                return session < login.session;
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 <                                return this->login < login.login;
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::set<Login> logins;
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 >                        std::string directory(login->second.GetDirectory());
150 >
151 >                        stream << "Login: " << login->first << std::string(33 - login->first.size(), ' ') << "Name: " << login->second.GetName() << "\r\nDirectory: " << directory << "\r\n";
152 >
153 >                        for (std::multimap<std::string, Login>::const_iterator login_(logins.lower_bound(login->first)); login_ != logins.upper_bound(login->first); ++login_)
154 >                                stream << login_->second.status << ' ' << login_->second.session << ' ' << login_->second.id << "\r\n";
155 >
156 >                        std::string files[] = { "\\.project", "\\.plan" };
157 >
158 >                        for (std::string *file(files); file != files + sizeof (files) / sizeof (*file); ++file)
159 >                        {
160 >                                file->insert(0, directory);
161 >
162 >                                std::ifstream in(file->c_str());
163 >
164 >                                if (!in.is_open())
165 >                                        continue;
166 >
167 >                                switch (file - files)
168 >                                {
169 >                                case 0:
170 >                                        stream << "Project:\r\n";
171 >
172 >                                        break;
173 >                                case 1:
174 >                                        stream << "Plan:\r\n";
175 >                                }
176 >
177 >                                std::string buffer;
178 >
179 >                                while (std::getline(in, buffer))
180 >                                        stream << buffer << std::endl;
181 >                        }
182 >                }
183 >        }
184  
185   public:
186          Finger(bool full)
# Line 59 | Line 197 | public:
197  
198                          ::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSUserName, &name, &size);
199  
200 <                        if (!std::wstring(name).empty())
200 >                        std::wstring name_(name);
201 >
202 >                        ::WTSFreeMemory(name);
203 >
204 >                        if (!name_.empty())
205                          {
206 +                                std::transform(name_.begin(), name_.end(), name_.begin(), std::towlower);
207 +
208                                  LPTSTR session_;
209  
210                                  ::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSWinStationName, &session_, &size);
211  
212 <                                Login login(Utf8(name), Utf8(session_));
212 >                                Login login(name_, session->SessionId, session_, session->State);
213  
214                                  ::WTSFreeMemory(session_);
215  
216 <                                logins.insert(login);
216 >                                logins.insert(std::make_pair(Utf8(name_), login));
217                          }
74
75                        ::WTSFreeMemory(name);
218                  }
219  
220                  ::WTSFreeMemory(sessions);
221  
222                  if (!full)
223                  {
224 <                        stream << "Login\t\tName" << std::string(17, ' ') << "Session\r\n";
224 >                        stream << "Login" << std::string(11, ' ') << "Name" << std::string(17, ' ') << "Id     Session       Status\r\n";
225  
226 <                        for (std::set<Login>::const_iterator login(logins.begin()); login != logins.end(); ++login)
227 <                                stream << login->login << std::string(16 - login->login.size(), ' ') << login->name << std::string(21 - login->name.size(), ' ') << login->session << "\r\n";
226 >                        for (std::multimap<std::string, Login>::const_iterator login(logins.begin()); login != logins.end(); ++login)
227 >                                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";
228                  }
229 +                else
230 +                        Full();
231          }
232  
233          Finger(const std::string &name)
# Line 114 | Line 258 | void WINAPI FingerControl(DWORD control)
258  
259   int _tmain(int argc, TCHAR *argv[])
260   {
261 <        SERVICE_TABLE_ENTRY entry[] = { { TEXT("CCS Finger Daemon"), LPSERVICE_MAIN_FUNCTION(FingerMain) }, { NULL, NULL } };
261 >        SERVICE_TABLE_ENTRY entry[] = { { TEXT("CCSFinger"), LPSERVICE_MAIN_FUNCTION(FingerMain) }, { NULL, NULL } };
262  
263          if (!::StartServiceCtrlDispatcher(entry))
264          {
# Line 145 | Line 289 | int _tmain(int argc, TCHAR *argv[])
289          return 0;
290  
291   go:
292 +        for (int index(1); index != argc; ++index)
293 +        {
294 +                std::wstring arg(argv[index]);
295 +
296 +                if (arg == TEXT("create"))
297 +                {
298 +                        TCHAR file[MAX_PATH];
299 +
300 +                        ::GetModuleFileName(NULL, file, MAX_PATH);
301 +
302 +                        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("")));
303 +
304 +                        if (!service)
305 +                                std::cerr << ::GetLastError() << std::endl;
306 +                        else
307 +                                ::CloseServiceHandle(service);
308 +
309 +                        ::CloseServiceHandle(manager);
310 +
311 +                        return 0;
312 +                }
313 +                else if (arg == TEXT("delete"))
314 +                {
315 +                        SC_HANDLE manager(::OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, DELETE)), service(::OpenService(manager, TEXT("CCSFinger"), DELETE));
316 +
317 +                        if (!::DeleteService(service))
318 +                                std::cerr << ::GetLastError() << std::endl;
319 +
320 +                        ::CloseServiceHandle(service);
321 +                        ::CloseServiceHandle(manager);
322 +
323 +                        return 0;
324 +                }
325 +        }
326 +
327          stop = ::CreateEvent(NULL, TRUE, FALSE, NULL);
328  
329          ::signal(SIGINT, FingerStop);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines