ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/CCSFinger/CCSFinger.cpp
Revision: 612
Committed: 2005-12-05T02:32:27-08:00 (19 years, 6 months ago) by douglas
File size: 5370 byte(s)
Log Message:
That, too.

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