ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/CCSFinger/CCSFinger.cpp
Revision: 610
Committed: 2005-12-05T01:05:13-08:00 (19 years, 6 months ago) by douglas
File size: 5261 byte(s)
Log Message:
Hmm!

File Contents

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