Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

481 lines
12 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // sockio.c - winsock i/o functions
  24. ////
  25. #include "winlocal.h"
  26. #include <mmsystem.h>
  27. #include <winsock.h>
  28. #include "sockio.h"
  29. #include "trace.h"
  30. #include "str.h"
  31. ////
  32. // private definitions
  33. ////
  34. // sock control struct
  35. //
  36. typedef struct SOCK
  37. {
  38. WSADATA wsaData;
  39. LPTSTR lpszServerName;
  40. unsigned short uPort;
  41. SOCKADDR_IN sin;
  42. SOCKET iSocket;
  43. } SOCK, FAR *LPSOCK;
  44. #define PORT_DEFAULT 1024
  45. // helper functions
  46. //
  47. static LRESULT SockIOOpen(LPMMIOINFO lpmmioinfo, LPTSTR lpszFileName);
  48. static LRESULT SockIOClose(LPMMIOINFO lpmmioinfo, UINT uFlags);
  49. static LRESULT SockIORead(LPMMIOINFO lpmmioinfo, HPSTR pch, LONG cch);
  50. static LRESULT SockIOWrite(LPMMIOINFO lpmmioinfo, const HPSTR pch, LONG cch, BOOL fFlush);
  51. static LRESULT SockIOSeek(LPMMIOINFO lpmmioinfo, LONG lOffset, int iOrigin);
  52. static LRESULT SockIORename(LPMMIOINFO lpmmioinfo, LPCTSTR lpszFileName, LPCTSTR lpszNewFileName);
  53. ////
  54. // public functions
  55. ////
  56. // SockIOProc - i/o procedure for winsock data
  57. // <lpmmioinfo> (i/o) information about open file
  58. // <uMessage> (i) message indicating the requested I/O operation
  59. // <lParam1> (i) message specific parameter
  60. // <lParam2> (i) message specific parameter
  61. // returns 0 if message not recognized, otherwise message specific value
  62. //
  63. // NOTE: the address of this function should be passed to the WavOpen()
  64. // or mmioInstallIOProc() functions for accessing property data.
  65. //
  66. LRESULT DLLEXPORT CALLBACK SockIOProc(LPSTR lpmmioinfo,
  67. UINT uMessage, LPARAM lParam1, LPARAM lParam2)
  68. {
  69. BOOL fSuccess = TRUE;
  70. LRESULT lResult = 0;
  71. if (lpmmioinfo == NULL)
  72. fSuccess = TraceFALSE(NULL);
  73. else switch (uMessage)
  74. {
  75. case MMIOM_OPEN:
  76. lResult = SockIOOpen((LPMMIOINFO) lpmmioinfo,
  77. (LPTSTR) lParam1);
  78. break;
  79. case MMIOM_CLOSE:
  80. lResult = SockIOClose((LPMMIOINFO) lpmmioinfo,
  81. (UINT) lParam1);
  82. break;
  83. case MMIOM_READ:
  84. lResult = SockIORead((LPMMIOINFO) lpmmioinfo,
  85. (HPSTR) lParam1, (LONG) lParam2);
  86. break;
  87. case MMIOM_WRITE:
  88. lResult = SockIOWrite((LPMMIOINFO) lpmmioinfo,
  89. (const HPSTR) lParam1, (LONG) lParam2, FALSE);
  90. break;
  91. case MMIOM_WRITEFLUSH:
  92. lResult = SockIOWrite((LPMMIOINFO) lpmmioinfo,
  93. (const HPSTR) lParam1, (LONG) lParam2, TRUE);
  94. break;
  95. case MMIOM_SEEK:
  96. lResult = SockIOSeek((LPMMIOINFO) lpmmioinfo,
  97. (LONG) lParam1, (int) lParam2);
  98. break;
  99. case MMIOM_RENAME:
  100. lResult = SockIORename((LPMMIOINFO) lpmmioinfo,
  101. (LPCTSTR) lParam1, (LPCTSTR) lParam2);
  102. break;
  103. default:
  104. lResult = 0;
  105. break;
  106. }
  107. return lResult;
  108. }
  109. ////
  110. // installable file i/o procedures
  111. ////
  112. static LRESULT SockIOOpen(LPMMIOINFO lpmmioinfo, LPTSTR lpszFileName)
  113. {
  114. BOOL fSuccess = TRUE;
  115. int nRet;
  116. LPSOCK lpSock = NULL;
  117. LPTSTR lpsz;
  118. TracePrintf_0(NULL, 5,
  119. TEXT("SockIOOpen\n"));
  120. // convert MMIOINFO flags to equivalent socket flags
  121. //
  122. if (lpmmioinfo->dwFlags & MMIO_CREATE)
  123. ;
  124. if (lpmmioinfo->dwFlags & MMIO_READWRITE)
  125. ;
  126. // server name pointer is first element of info array
  127. //
  128. if ((LPTSTR) lpmmioinfo->adwInfo[0] == NULL)
  129. fSuccess = TraceFALSE(NULL);
  130. // allocate control struct
  131. //
  132. else if ((lpSock = (LPSOCK) GlobalAllocPtr(GMEM_MOVEABLE |
  133. GMEM_ZEROINIT, sizeof(SOCK))) == NULL)
  134. {
  135. fSuccess = TraceFALSE(NULL);
  136. }
  137. // initialize Windows Sockets DLL, requesting v1.1 compatibility
  138. //
  139. else if ((nRet = WSAStartup(0x0101, &lpSock->wsaData)) != 0)
  140. {
  141. fSuccess = TraceFALSE(NULL);
  142. TracePrintf_1(NULL, 5,
  143. TEXT("WSAStartup failed (%d)\n"),
  144. (int) nRet);
  145. }
  146. // Confirm that the Windows Sockets DLL supports winsock v1.1
  147. //
  148. else if (LOBYTE(lpSock->wsaData.wVersion) != 1 ||
  149. HIBYTE(lpSock->wsaData.wVersion) != 1)
  150. {
  151. fSuccess = TraceFALSE(NULL);
  152. TracePrintf_0(NULL, 5,
  153. TEXT("Winsock is not v1.1 compatible\n"));
  154. }
  155. // save copy of server name
  156. //
  157. else if ((lpSock->lpszServerName =
  158. (LPTSTR) StrDup((LPTSTR) lpmmioinfo->adwInfo[0])) == NULL)
  159. fSuccess = TraceFALSE(NULL);
  160. // parse out port number if present (servername:port)
  161. //
  162. else if ((lpsz = StrRChr(lpSock->lpszServerName, ':')) != NULL)
  163. {
  164. *lpsz = '\0';
  165. lpSock->uPort = (unsigned int) StrAtoI(lpsz + 1);
  166. }
  167. // otherwise assume default port
  168. //
  169. else
  170. lpSock->uPort = PORT_DEFAULT;
  171. // construct server's socket address struct
  172. //
  173. if (fSuccess)
  174. {
  175. LPHOSTENT lpHostEnt = NULL;
  176. // address family must be internetwork: UDP, TCP, etc.
  177. //
  178. lpSock->sin.sin_family = AF_INET;
  179. // convert port from host byte order to network byte order
  180. //
  181. lpSock->sin.sin_port = htons(lpSock->uPort);
  182. // if servername contains anything other than digits and periods
  183. //
  184. if (StrSpn(lpSock->lpszServerName, TEXT(".0123456789")) !=
  185. StrLen(lpSock->lpszServerName))
  186. {
  187. // try to resolve with DNS
  188. //
  189. if ((lpHostEnt = gethostbyname(lpSock->lpszServerName)) == NULL)
  190. {
  191. TracePrintf_2(NULL, 5,
  192. TEXT("gethostbyname(%s) failed (%d)\n"),
  193. (LPTSTR) lpSock->lpszServerName,
  194. (int) WSAGetLastError());
  195. }
  196. // store resolved address
  197. //
  198. else
  199. {
  200. lpSock->sin.sin_addr.s_addr =
  201. *((LPDWORD) lpHostEnt->h_addr);
  202. }
  203. }
  204. // if servername contains only digits and periods,
  205. // or if gethostbyname() failed, convert address string to binary
  206. //
  207. if (lpHostEnt == NULL)
  208. {
  209. if ((lpSock->sin.sin_addr.s_addr =
  210. inet_addr(lpSock->lpszServerName)) == INADDR_NONE)
  211. {
  212. fSuccess = TraceFALSE(NULL);
  213. TracePrintf_1(NULL, 5,
  214. TEXT("inet_addr(%s) failed\n"),
  215. (LPTSTR) lpSock->lpszServerName);
  216. }
  217. }
  218. }
  219. if (fSuccess)
  220. {
  221. LINGER l;
  222. l.l_onoff = 1;
  223. l.l_linger = 0;
  224. // create a socket
  225. //
  226. if ((lpSock->iSocket = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
  227. {
  228. fSuccess = TraceFALSE(NULL);
  229. TracePrintf_1(NULL, 5,
  230. TEXT("socket() failed (%d)\n"),
  231. (int) WSAGetLastError());
  232. }
  233. // establish a socket connection to server
  234. //
  235. else if (connect(lpSock->iSocket, (LPSOCKADDR) &lpSock->sin,
  236. sizeof(lpSock->sin)) == SOCKET_ERROR)
  237. {
  238. fSuccess = TraceFALSE(NULL);
  239. TracePrintf_1(NULL, 5,
  240. TEXT("connect() failed (%d)\n"),
  241. (int) WSAGetLastError());
  242. }
  243. // enable SO_LINGER option so that closesocket() will discard
  244. // unsent data rather than block until queued data is sent
  245. //
  246. else if (setsockopt(lpSock->iSocket, SOL_SOCKET, SO_LINGER,
  247. (LPVOID) &l, sizeof(l)) == SOCKET_ERROR)
  248. {
  249. fSuccess = TraceFALSE(NULL);
  250. TracePrintf_1(NULL, 5,
  251. TEXT("setsockopt(SO_LINGER) failed (%d)\n"),
  252. (int) WSAGetLastError());
  253. }
  254. }
  255. if (fSuccess)
  256. {
  257. // save socket control struct pointer for use in other i/o routines
  258. //
  259. lpmmioinfo->adwInfo[0] = (DWORD) (LPVOID) lpSock;
  260. }
  261. // return the same error code given by mmioOpen
  262. //
  263. return fSuccess ? lpmmioinfo->wErrorRet = 0 : MMIOERR_CANNOTOPEN;
  264. }
  265. static LRESULT SockIOClose(LPMMIOINFO lpmmioinfo, UINT uFlags)
  266. {
  267. BOOL fSuccess = TRUE;
  268. LPSOCK lpSock = (LPSOCK) lpmmioinfo->adwInfo[0];
  269. UINT uRet = MMIOERR_CANNOTCLOSE;
  270. TracePrintf_0(NULL, 5,
  271. TEXT("SockIOClose\n"));
  272. // cancel any blocking call if necessary
  273. //
  274. if (WSAIsBlocking() && WSACancelBlockingCall() == SOCKET_ERROR)
  275. {
  276. fSuccess = TraceFALSE(NULL);
  277. TracePrintf_1(NULL, 5,
  278. TEXT("WSACancelBlockingCall() failed (%d)\n"),
  279. (int) WSAGetLastError());
  280. }
  281. // close the socket
  282. //
  283. else if (lpSock->iSocket != INVALID_SOCKET &&
  284. closesocket(lpSock->iSocket) == SOCKET_ERROR)
  285. {
  286. fSuccess = TraceFALSE(NULL);
  287. TracePrintf_1(NULL, 5,
  288. TEXT("closesocket() failed (%d)\n"),
  289. (int) WSAGetLastError());
  290. }
  291. else
  292. lpSock->iSocket = INVALID_SOCKET;
  293. if (fSuccess)
  294. {
  295. // free server name buffer
  296. //
  297. if (lpSock->lpszServerName != NULL &&
  298. StrDupFree(lpSock->lpszServerName) != 0)
  299. {
  300. fSuccess = TraceFALSE(NULL);
  301. }
  302. else
  303. lpSock->lpszServerName = NULL;
  304. }
  305. if (fSuccess)
  306. {
  307. lpmmioinfo->adwInfo[0] = (DWORD) NULL;
  308. }
  309. return fSuccess ? 0 : uRet;
  310. }
  311. static LRESULT SockIORead(LPMMIOINFO lpmmioinfo, HPSTR pch, LONG cch)
  312. {
  313. BOOL fSuccess = TRUE;
  314. LPSOCK lpSock = (LPSOCK) lpmmioinfo->adwInfo[0];
  315. int nBytesRead;
  316. TracePrintf_1(NULL, 5,
  317. TEXT("SockIORead (%ld)\n"),
  318. (long) cch);
  319. if (cch <= 0)
  320. nBytesRead = 0; // nothing to do
  321. // read
  322. //
  323. else if ((nBytesRead = recv(lpSock->iSocket,
  324. (LPVOID) pch, (int) cch, 0)) == SOCKET_ERROR)
  325. {
  326. fSuccess = TraceFALSE(NULL);
  327. TracePrintf_1(NULL, 5,
  328. TEXT("recv() failed (%d)\n"),
  329. (int) WSAGetLastError());
  330. }
  331. // update simulated file position
  332. //
  333. else
  334. lpmmioinfo->lDiskOffset += (LONG) nBytesRead;
  335. TracePrintf_2(NULL, 5,
  336. TEXT("SockIO: lpmmioinfo->lDiskOffset=%ld, lBytesRead=%ld\n"),
  337. (long) lpmmioinfo->lDiskOffset,
  338. (long) nBytesRead);
  339. // return number of bytes read
  340. //
  341. return fSuccess ? (LRESULT) nBytesRead : -1;
  342. }
  343. static LRESULT SockIOWrite(LPMMIOINFO lpmmioinfo, const HPSTR pch, LONG cch, BOOL fFlush)
  344. {
  345. BOOL fSuccess = TRUE;
  346. LPSOCK lpSock = (LPSOCK) lpmmioinfo->adwInfo[0];
  347. int nBytesWritten;
  348. TracePrintf_1(NULL, 5,
  349. TEXT("SockIOWrite (%ld)\n"),
  350. (long) cch);
  351. if (cch <= 0)
  352. nBytesWritten = 0; // nothing to do
  353. // write
  354. //
  355. else if ((nBytesWritten = send(lpSock->iSocket,
  356. (LPVOID) pch, (int) cch, 0)) == SOCKET_ERROR)
  357. {
  358. fSuccess = TraceFALSE(NULL);
  359. TracePrintf_1(NULL, 5,
  360. TEXT("send() failed (%d)\n"),
  361. (int) WSAGetLastError());
  362. }
  363. // update file position
  364. //
  365. else
  366. lpmmioinfo->lDiskOffset += (LONG) nBytesWritten;
  367. TracePrintf_2(NULL, 5,
  368. TEXT("SockIO: lpmmioinfo->lDiskOffset=%ld, lBytesWritten=%ld\n"),
  369. (long) lpmmioinfo->lDiskOffset,
  370. (long) nBytesWritten);
  371. // return number of bytes written
  372. //
  373. return fSuccess ? (LRESULT) nBytesWritten : -1;
  374. }
  375. static LRESULT SockIOSeek(LPMMIOINFO lpmmioinfo, LONG lOffset, int iOrigin)
  376. {
  377. BOOL fSuccess = TRUE;
  378. LPSOCK lpSock = (LPSOCK) lpmmioinfo->adwInfo[0];
  379. TracePrintf_2(NULL, 5,
  380. TEXT("SockIOSeek (%ld, %d)\n"),
  381. (long) lOffset,
  382. (int) iOrigin);
  383. // seek is not supported by this i/o procedure
  384. //
  385. if (TRUE)
  386. fSuccess = TraceFALSE(NULL);
  387. TracePrintf_1(NULL, 5,
  388. TEXT("SockIO: lpmmioinfo->lDiskOffset=%ld\n"),
  389. (long) lpmmioinfo->lDiskOffset);
  390. return fSuccess ? lpmmioinfo->lDiskOffset : -1;
  391. }
  392. static LRESULT SockIORename(LPMMIOINFO lpmmioinfo, LPCTSTR lpszFileName, LPCTSTR lpszNewFileName)
  393. {
  394. BOOL fSuccess = TRUE;
  395. UINT uRet = MMIOERR_FILENOTFOUND;
  396. TracePrintf_2(NULL, 5,
  397. TEXT("SockIORename (%s, %s)\n"),
  398. (LPTSTR) lpszFileName,
  399. (LPTSTR) lpszNewFileName);
  400. // rename is not supported by this i/o procedure
  401. //
  402. if (TRUE)
  403. fSuccess = TraceFALSE(NULL);
  404. return fSuccess ? 0 : uRet;
  405. }