ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/CCSFinger/CCSFinger.cpp
Revision: 611
Committed: 2005-12-05T01:26:27-08:00 (19 years, 7 months ago) by douglas
File size: 5318 byte(s)
Log Message:
Umm...

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