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, 7 months ago) by douglas
File size: 5370 byte(s)
Log Message:
That, too.

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