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

# 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 douglas 611 std::string name_(Utf8(name));
50 douglas 610
51 douglas 611 if (!name_.empty())
52     stream << name_ << "\r\n";
53    
54 douglas 610 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 douglas 595 LPTSTR name;
75 douglas 594 SERVICE_STATUS status;
76     SERVICE_STATUS_HANDLE handle;
77 douglas 595 HANDLE stop;
78 douglas 594 WSADATA data;
79 douglas 609 std::vector<HANDLE> threads;
80 douglas 594
81 douglas 596 void FingerDaemon();
82 douglas 609 DWORD WINAPI FingerListen(LPVOID server_);
83     DWORD WINAPI FingerDo(LPVOID client_);
84 douglas 596 void FingerStop(int);
85 douglas 595 void WINAPI FingerMain(DWORD argc, LPTSTR *argv);
86     void WINAPI FingerControl(DWORD control);
87 douglas 594
88     int _tmain(int argc, TCHAR *argv[])
89     {
90 douglas 609 SERVICE_TABLE_ENTRY entry[] = { { TEXT("CCS Finger Daemon"), LPSERVICE_MAIN_FUNCTION(FingerMain) }, { NULL, NULL } };
91 douglas 594
92     if (!StartServiceCtrlDispatcher(entry))
93     {
94     DWORD error(GetLastError());
95    
96     switch (error)
97     {
98     case ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
99 douglas 595 goto go;
100 douglas 594
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 douglas 595
120     go:
121 douglas 608 stop = CreateEvent(NULL, TRUE, FALSE, NULL);
122    
123 douglas 596 signal(SIGINT, FingerStop);
124 douglas 595
125 douglas 596 try
126     {
127     FingerDaemon();
128     }
129     catch (...) {}
130    
131 douglas 609 return 0;
132 douglas 594 }
133    
134 douglas 596 void FingerDaemon()
135 douglas 594 {
136     WSAStartup(MAKEWORD(2, 0), &data);
137    
138     //
139    
140 douglas 608 SOCKET server(socket(PF_INET, SOCK_STREAM, IPPROTO_TCP));
141 douglas 594 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 douglas 608 bind(server, (SOCKADDR *)(&service), sizeof (service));
148     listen(server, SOMAXCONN);
149 douglas 594
150 douglas 609 threads.push_back(CreateThread(NULL, 0, FingerListen, &server, 0, NULL));
151 douglas 608
152 douglas 609 while(WaitForSingleObject(stop, 1000) != WAIT_OBJECT_0);
153 douglas 594
154     //
155    
156 douglas 608 closesocket(server);
157    
158 douglas 594 WSACleanup();
159 douglas 596 }
160 douglas 594
161 douglas 609 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 douglas 610 char buffer[1024];
179     std::istringstream stream(std::string(buffer, recv(client, buffer, sizeof buffer, 0)));
180     std::string line;
181 douglas 609
182 douglas 610 std::getline(stream, line);
183 douglas 609
184 douglas 610 stream.str(line);
185 douglas 609
186 douglas 610 std::getline(stream, line, '\r');
187 douglas 609
188 douglas 610 stream.str(line);
189 douglas 609
190 douglas 610 std::string name;
191     bool full(false);
192 douglas 609
193 douglas 610 while (stream >> line)
194     if (line == "/W")
195     full = true;
196     else
197     name = line;
198 douglas 609
199 douglas 610 std::string finger(name.empty() ? Finger(full) : Finger(name));
200 douglas 609
201 douglas 610 send(client, finger.data(), int(finger.size()), 0);
202 douglas 609 closesocket(client);
203    
204     return 0;
205     }
206    
207 douglas 596 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 douglas 595 status.dwCurrentState = SERVICE_STOPPED;
237 douglas 594 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 douglas 595 SetServiceStatus(handle, &status);
261 douglas 594 }