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, 7 months ago) by douglas
File size: 5261 byte(s)
Log Message:
Hmm!

File Contents

# User Rev Content
1 douglas 594 // Douglas Thrift
2     //
3     // CCS Computer Science
4     //
5     // Windows Finger Daemon
6    
7     #include <windows.h>
8     #include <tchar.h>
9 douglas 596 #include <signal.h>
10 douglas 608 #include <wtsapi32.h>
11 douglas 594
12 douglas 595 #include <iostream>
13 douglas 608 #include <string>
14 douglas 610 #include <sstream>
15 douglas 609 #include <vector>
16 douglas 595
17 douglas 610 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 douglas 595 LPTSTR name;
72 douglas 594 SERVICE_STATUS status;
73     SERVICE_STATUS_HANDLE handle;
74 douglas 595 HANDLE stop;
75 douglas 594 WSADATA data;
76 douglas 609 std::vector<HANDLE> threads;
77 douglas 594
78 douglas 596 void FingerDaemon();
79 douglas 609 DWORD WINAPI FingerListen(LPVOID server_);
80     DWORD WINAPI FingerDo(LPVOID client_);
81 douglas 596 void FingerStop(int);
82 douglas 595 void WINAPI FingerMain(DWORD argc, LPTSTR *argv);
83     void WINAPI FingerControl(DWORD control);
84 douglas 594
85     int _tmain(int argc, TCHAR *argv[])
86     {
87 douglas 609 SERVICE_TABLE_ENTRY entry[] = { { TEXT("CCS Finger Daemon"), LPSERVICE_MAIN_FUNCTION(FingerMain) }, { NULL, NULL } };
88 douglas 594
89     if (!StartServiceCtrlDispatcher(entry))
90     {
91     DWORD error(GetLastError());
92    
93     switch (error)
94     {
95     case ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
96 douglas 595 goto go;
97 douglas 594
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 douglas 595
117     go:
118 douglas 608 stop = CreateEvent(NULL, TRUE, FALSE, NULL);
119    
120 douglas 596 signal(SIGINT, FingerStop);
121 douglas 595
122 douglas 596 try
123     {
124     FingerDaemon();
125     }
126     catch (...) {}
127    
128 douglas 609 return 0;
129 douglas 594 }
130    
131 douglas 596 void FingerDaemon()
132 douglas 594 {
133     WSAStartup(MAKEWORD(2, 0), &data);
134    
135     //
136    
137 douglas 608 SOCKET server(socket(PF_INET, SOCK_STREAM, IPPROTO_TCP));
138 douglas 594 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 douglas 608 bind(server, (SOCKADDR *)(&service), sizeof (service));
145     listen(server, SOMAXCONN);
146 douglas 594
147 douglas 609 threads.push_back(CreateThread(NULL, 0, FingerListen, &server, 0, NULL));
148 douglas 608
149 douglas 609 while(WaitForSingleObject(stop, 1000) != WAIT_OBJECT_0);
150 douglas 594
151     //
152    
153 douglas 608 closesocket(server);
154    
155 douglas 594 WSACleanup();
156 douglas 596 }
157 douglas 594
158 douglas 609 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 douglas 610 char buffer[1024];
176     std::istringstream stream(std::string(buffer, recv(client, buffer, sizeof buffer, 0)));
177     std::string line;
178 douglas 609
179 douglas 610 std::getline(stream, line);
180 douglas 609
181 douglas 610 stream.str(line);
182 douglas 609
183 douglas 610 std::getline(stream, line, '\r');
184 douglas 609
185 douglas 610 stream.str(line);
186 douglas 609
187 douglas 610 std::string name;
188     bool full(false);
189 douglas 609
190 douglas 610 while (stream >> line)
191     if (line == "/W")
192     full = true;
193     else
194     name = line;
195 douglas 609
196 douglas 610 std::string finger(name.empty() ? Finger(full) : Finger(name));
197 douglas 609
198 douglas 610 send(client, finger.data(), int(finger.size()), 0);
199 douglas 609 closesocket(client);
200    
201     return 0;
202     }
203    
204 douglas 596 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 douglas 595 status.dwCurrentState = SERVICE_STOPPED;
234 douglas 594 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 douglas 595 SetServiceStatus(handle, &status);
258 douglas 594 }