]> git.8kb.co.uk Git - dataflex/df32func/blob - src/c/df32func.c
Just pushing the latest copy of my development / staging DataFlex stuff into git...
[dataflex/df32func] / src / c / df32func.c
1 /*-------------------------------------------------------------------------\r
2  * df32func.c\r
3  *     df32func extensions for Console Mode DataFlex 3.2\r
4  *\r
5  * Copyright (c) 2007-2015, glyn@8kb.co.uk\r
6  * Author: Glyn Astill <glyn@8kb.co.uk>\r
7  *\r
8  *-------------------------------------------------------------------------\r
9  */\r
10 \r
11 #include <windows.h>\r
12 #include <stdio.h>\r
13 #include <stdlib.h>\r
14 #include <winsock.h>\r
15 #include <tchar.h>\r
16 #include "gnuregex.h"\r
17 #include "df32func.h"\r
18 \r
19 /*\r
20  * Used by GetTzi\r
21  * http://msdn.microsoft.com/en-us/library/ms724253.aspx\r
22  */\r
23 typedef struct _REG_TZI_FORMAT\r
24 {\r
25     LONG Bias;\r
26     LONG StandardBias;\r
27     LONG DaylightBias;\r
28     SYSTEMTIME StandardDate;\r
29     SYSTEMTIME DaylightDate;\r
30 } REG_TZI_FORMAT;\r
31 \r
32 SOCKET s, sc; /* Socket handle */\r
33 \r
34 /*\r
35  * The number of cycles used by the processor since the start obtained on x86\r
36  * processors (Intel, AMD), with the assembly command rdtsc.\r
37  */\r
38 int rdtsc()\r
39 {\r
40     __asm__ __volatile__("rdtsc");\r
41 }\r
42 \r
43 /*\r
44  * CLIENTSOCKET \96 Creates a communication socket and connects to a remote host on the\r
45  *                supplied port and IP\r
46  */\r
47 DLLIMPORT int ClientSocket(int PortNo, char* IPAddress){\r
48     /* Start up Winsock */\r
49     WSADATA wsadata;\r
50 \r
51     int error = WSAStartup(0x0202, &wsadata);\r
52 \r
53     /* Did something happen? */\r
54     if (error){\r
55         return -1;\r
56     }\r
57 \r
58     /* Did we get the right Winsock version? */\r
59     if (wsadata.wVersion != 0x0202){\r
60         WSACleanup(); /* Clean up Winsock */\r
61         return -1;\r
62     }\r
63 \r
64     /* Fill out the information needed to initialize a socket */\r
65     SOCKADDR_IN target; /* Socket address information */\r
66 \r
67     target.sin_family = AF_INET; /*  address family Internet */\r
68     target.sin_port = htons (PortNo); /* Port to connect on */\r
69     target.sin_addr.s_addr = inet_addr (IPAddress); /* Target IP */\r
70 \r
71     s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); /* Create socket */\r
72     if (s == INVALID_SOCKET){\r
73         return -1; /* Couldn't create the socket */\r
74     }\r
75 \r
76     /* Try connecting */\r
77     if (connect(s, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR){\r
78         return -1; /* Couldn't connect */\r
79     }\r
80     else{\r
81         return s; /* Success - return our socket number */\r
82     }\r
83 }\r
84 \r
85 /*\r
86  * SERVERSOCKET \96 Creates a communication socket and a tcp server listening on a the\r
87  *                supplied port number\r
88  */\r
89 DLLIMPORT int ServerSocket(int PortNo){\r
90     /* Start up Winsock */\r
91     WSADATA wsadata;\r
92 \r
93     int error = WSAStartup(0x0202, &wsadata);\r
94 \r
95     /* Did something happen? */\r
96     if (error){\r
97         return -1;\r
98     }\r
99 \r
100     /* Did we get the right Winsock version? */\r
101     if (wsadata.wVersion != 0x0202){\r
102         WSACleanup(); /* Clean up Winsock */\r
103         return -1;\r
104     }\r
105 \r
106     /* Fill out the information needed to initialize a socket */\r
107     SOCKADDR_IN target; /* Socket address information */\r
108 \r
109     target.sin_family = AF_INET; /*  address family Internet */\r
110     target.sin_port = htons (PortNo); /* Port to connect on */\r
111     target.sin_addr.s_addr = INADDR_ANY; /* Target IP */\r
112 \r
113     s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); /* Create socket */\r
114     if (s == INVALID_SOCKET){\r
115         return -1; /* Couldn't create the socket */\r
116     }\r
117 \r
118     /* Try to bind to the socket */\r
119     if (bind(s, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR) {\r
120         return -1; /* Couldn't connect */\r
121     }\r
122     else{\r
123          /* Now we can start listening, We allow SOMNAXCONN connections. This will not return until we get a connection */\r
124          if (listen(s, SOMAXCONN) == SOCKET_ERROR) {\r
125                        return -1;\r
126          }\r
127          else{\r
128               return s;\r
129          }\r
130     }\r
131 }\r
132 \r
133 /*\r
134  * CLOSECONNECTION \96 shuts down a communication socket and closes any connection on it\r
135  */\r
136 DLLIMPORT void CloseConnection (int socket){\r
137     /* Close the socket if it exists */\r
138     if (socket){\r
139         closesocket(socket);\r
140     }\r
141 \r
142     WSACleanup(); /* Clean up Winsock */\r
143 }\r
144 \r
145 /*\r
146  * SEND - Send data over the communication socket\r
147  */\r
148 DLLIMPORT int Send(int socket, char* data){\r
149          return send(socket, data, strlen(data), 0);\r
150 }\r
151 \r
152 /*\r
153  * RECEIVE - Recieve data over the client socket\r
154  */\r
155 DLLIMPORT int Receive(int socket, char *pData){\r
156        char data[255] = {0};\r
157        int bytesIn = 0;\r
158 \r
159        memset(data, 0, sizeof(data));\r
160        bytesIn = recv(socket, data, sizeof(data), 0);\r
161        if (bytesIn == SOCKET_ERROR) {\r
162                   return -1;\r
163        }\r
164        sprintf (pData, "%s", data );\r
165        return bytesIn;\r
166 }\r
167 \r
168 /*\r
169  * ACCEPTCLIENT - Accept a client connection\r
170  */\r
171 DLLIMPORT int AcceptClient(){\r
172        SOCKADDR_IN client;\r
173        int clientSize = sizeof(client);\r
174        sc = accept(s, (SOCKADDR *)&client, &clientSize);\r
175        if (sc == INVALID_SOCKET){\r
176               return -1;\r
177       }\r
178       return sc;\r
179 }\r
180 \r
181 /*\r
182  * Generate a pseudo random integer from an integer\r
183  */\r
184 DLLIMPORT unsigned int PseudoRand(unsigned int w){\r
185        unsigned int m_w = w;\r
186        unsigned int m_z = (w / 2);\r
187 \r
188        m_z = 36969 * (m_z & 65535) + (m_z >> 16);\r
189        m_w = 18000 * (m_w & 65535) + (m_w >> 16);\r
190        return (m_z << 16) + m_w;  /* 32-bit result */\r
191 }\r
192 \r
193 /*\r
194  * Generate a random integer from the cpu rdtsc\r
195  */\r
196 DLLIMPORT unsigned int RdtscRand(){\r
197      unsigned int n = 0;\r
198      int i;\r
199      /*  First digit must be non-zero: */\r
200      do\r
201      {\r
202             srand(rdtsc());\r
203             n = rand() % 8;\r
204      } while(n == 0);\r
205      for(i = 1; i < 8; i++)\r
206      {\r
207             n *= 8;\r
208             srand(rdtsc());\r
209             n += rand() % 8;\r
210      }\r
211      return n;\r
212 }\r
213 \r
214 /*\r
215  * Pull back timezone information from windows registry\r
216  */\r
217 DLLIMPORT int GetTzi (TCHAR* zone, TCHAR *result)\r
218 {\r
219     DWORD dwStatus, dwType, cbData;\r
220     int cch;\r
221     TCHAR szTime[128], szDate[128], szSubKey[256];\r
222     HKEY hKey;\r
223     REG_TZI_FORMAT tzi;\r
224 \r
225     /* https://msdn.microsoft.com/en-us/library/windows/desktop/ms647490%28v=vs.85%29.aspx */\r
226     lstrcpy(szSubKey, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\"));\r
227 \r
228     /*\r
229      * https://msdn.microsoft.com/en-us/library/aa272954%28v=vs.60%29.aspx\r
230      * https://msdn.microsoft.com/en-us/library/h1x0y282.aspx\r
231      */\r
232     _tcscat(szSubKey, zone);\r
233 \r
234     dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_QUERY_VALUE, &hKey);\r
235     if (dwStatus != NO_ERROR)\r
236         return GetLastError();\r
237 \r
238     cbData = sizeof(REG_TZI_FORMAT);\r
239     dwStatus = RegQueryValueEx (hKey, TEXT("TZI"), NULL, &dwType, (LPBYTE)&tzi, &cbData);\r
240     if (dwStatus != NO_ERROR)\r
241         return GetLastError();\r
242 \r
243     /*\r
244      * tzi.StandardDate and tzi.DaylightDate are not a real SYSTEMTIME\r
245      * but we should look at them to depict daylight saving\r
246      * if month = 0 then not supported, year = 0 means every year.\r
247      * http://msdn.microsoft.com/en-us/library/ms725481.asp\r
248      */\r
249 \r
250      _stprintf(result, "%d,%d,%d,%d/%d/%d/%d,%d:%d:%d,%d/%d/%d/%d,%d:%d:%d",\r
251                       tzi.Bias,tzi.StandardBias,tzi.DaylightBias,\r
252                       tzi.StandardDate.wYear,tzi.StandardDate.wMonth,tzi.StandardDate.wDay,tzi.StandardDate.wDayOfWeek,tzi.StandardDate.wHour,tzi.StandardDate.wMinute,tzi.StandardDate.wSecond,\r
253                       tzi.DaylightDate.wYear,tzi.DaylightDate.wMonth,tzi.DaylightDate.wDay,tzi.DaylightDate.wDayOfWeek,tzi.DaylightDate.wHour,tzi.DaylightDate.wMinute,tzi.DaylightDate.wSecond\r
254                       );\r
255 \r
256     return -1;\r
257 }\r
258 \r
259 /*\r
260  * Check for a regex match\r
261  */\r
262 DLLIMPORT int RegexpMatch (const char *str, const char *pattern, const char *flags, int errors)\r
263 {\r
264     return regexp_match(str, pattern, flags, errors);\r
265 }\r
266 \r
267 /*\r
268  * Return all matches in the regex as a string and return in custom format\r
269  */\r
270 DLLIMPORT int RegexpMatches(const char *str, const char *pattern, const char *flags, char *output, int output_len, int errors)\r
271 {\r
272     char        *matches = regexp_matches(str, pattern, flags, errors);\r
273     int         matches_len;\r
274     int         result = 0;\r
275 \r
276     if (matches != NULL)\r
277     {\r
278         matches_len = strlen(matches);\r
279         if (matches_len <= output_len)\r
280         {\r
281             strncpy(output, matches, matches_len);\r
282             result = 0;\r
283         }\r
284         else\r
285             result = -1;\r
286 \r
287         wfree(matches);\r
288     }\r
289     else\r
290         result = -2;\r
291 \r
292     return result;\r
293 }\r
294 \r
295 /*\r
296  * Substitutes matches with the regex pattern in the string with the replacement\r
297  * pattern/string.\r
298  */\r
299 DLLIMPORT int RegexpReplace(const char *str, const char *pattern, const char *replacement, const char *flags, char *output, int output_len, int errors)\r
300 {\r
301     char        *replaced = regexp_replace(str, pattern, replacement, flags, errors);\r
302     int         replaced_len;\r
303     int         result = 0;\r
304 \r
305     if (replaced != NULL)\r
306     {\r
307         replaced_len = strlen(replaced);\r
308 \r
309         if (replaced_len <= output_len)\r
310         {\r
311             strncpy(output, replaced, replaced_len);\r
312             result = 0;\r
313         }\r
314         else\r
315             result = -1;\r
316 \r
317         wfree(replaced);\r
318     }\r
319     else\r
320         result = -2;\r
321 \r
322 \r
323     return result;\r
324 }\r
325 \r
326 \r
327 /*\r
328  * DLL entry point\r
329  */\r
330 BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,\r
331                        DWORD reason        /* Reason this function is being called. */ ,\r
332                        LPVOID reserved     /* Not used. */ )\r
333 {\r
334     switch (reason)\r
335     {\r
336       case DLL_PROCESS_ATTACH:\r
337         break;\r
338 \r
339       case DLL_PROCESS_DETACH:\r
340         break;\r
341 \r
342       case DLL_THREAD_ATTACH:\r
343         break;\r
344 \r
345       case DLL_THREAD_DETACH:\r
346         break;\r
347     }\r
348 \r
349     /* Returns TRUE on success, FALSE on failure */\r
350     return TRUE;\r
351 }\r