Source code of Windows XP (NT5)
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.

464 lines
11 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1996
  5. //
  6. // File: mailslot.cpp
  7. //
  8. // Contents:
  9. //
  10. // History:
  11. //
  12. // Note:
  13. //---------------------------------------------------------------------------
  14. #include "pch.cpp"
  15. #include <tchar.h>
  16. #include <process.h>
  17. #include "lscommon.h"
  18. #include "debug.h"
  19. #include "globals.h"
  20. typedef DWORD (* LSPROTOCOLHANDLER)(DWORD cbData, PBYTE pbData);
  21. typedef struct _ProtocolFuncMapper {
  22. LPTSTR szProtocol;
  23. LSPROTOCOLHANDLER func;
  24. } ProtocolFuncMapper;
  25. DWORD HandleDiscovery( DWORD cbData, PBYTE pbData );
  26. DWORD HandleChallenge( DWORD cbData, PBYTE pbData );
  27. ProtocolFuncMapper pfm[] = {
  28. {_TEXT(LSERVER_DISCOVERY), HandleDiscovery},
  29. {_TEXT(LSERVER_CHALLENGE), HandleChallenge}
  30. };
  31. DWORD dwNumProtocol=sizeof(pfm) / sizeof(pfm[0]);
  32. //--------------------------------------------------------------------
  33. DWORD
  34. HandleDiscovery(
  35. DWORD cbData,
  36. PBYTE pbData
  37. )
  38. /*++
  39. ++*/
  40. {
  41. TCHAR szDiscMsg[MAX_MAILSLOT_MSG_SIZE+1];
  42. TCHAR szPipeName[MAX_MAILSLOT_MSG_SIZE+20];
  43. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+2];
  44. DWORD cbComputerName = MAX_COMPUTERNAME_LENGTH+1;
  45. DWORD byteWritten = 0;
  46. LPTSTR pClientName;
  47. LPTSTR pMailSlot;
  48. LPTSTR ePtr;
  49. DWORD dwStatus=ERROR_SUCCESS;
  50. HANDLE hSlot = INVALID_HANDLE_VALUE;
  51. if(cbData >= sizeof(szDiscMsg)-sizeof(TCHAR))
  52. {
  53. dwStatus = ERROR_INVALID_PARAMETER;
  54. return dwStatus;
  55. }
  56. //
  57. // Prevent no NULL terminated input
  58. //
  59. memset(szDiscMsg, 0, sizeof(szDiscMsg));
  60. memcpy(szDiscMsg, pbData, cbData);
  61. GetComputerName(szComputerName, &cbComputerName);
  62. do {
  63. //
  64. // Extract client machine name
  65. //
  66. pClientName=_tcschr(szDiscMsg, _TEXT(LSERVER_OPEN_BLK));
  67. if(pClientName == NULL)
  68. {
  69. DBGPrintf(
  70. DBG_INFORMATION,
  71. DBG_FACILITY_RPC,
  72. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  73. _TEXT("Can't find beginning client name\n")
  74. );
  75. dwStatus = ERROR_INVALID_PARAMETER;
  76. break;
  77. }
  78. pClientName = _tcsinc(pClientName);
  79. ePtr=_tcschr(pClientName, _TEXT(LSERVER_CLOSE_BLK));
  80. if(ePtr == NULL)
  81. {
  82. DBGPrintf(
  83. DBG_INFORMATION,
  84. DBG_FACILITY_RPC,
  85. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  86. _TEXT("Can't find ending client name\n")
  87. );
  88. dwStatus = ERROR_INVALID_PARAMETER;
  89. break;
  90. }
  91. *ePtr = _TEXT('\0');
  92. //
  93. // Extract Mailslot name
  94. //
  95. ePtr = _tcsinc(ePtr);
  96. pMailSlot = _tcschr(ePtr, _TEXT(LSERVER_OPEN_BLK));
  97. if(pMailSlot == NULL)
  98. {
  99. DBGPrintf(
  100. DBG_INFORMATION,
  101. DBG_FACILITY_RPC,
  102. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  103. _TEXT("Can't find beginning mailslot name\n")
  104. );
  105. dwStatus = ERROR_INVALID_PARAMETER;
  106. break;
  107. }
  108. pMailSlot = _tcsinc(pMailSlot);
  109. ePtr=_tcschr(pMailSlot, _TEXT(LSERVER_CLOSE_BLK));
  110. if(ePtr == NULL)
  111. {
  112. DBGPrintf(
  113. DBG_INFORMATION,
  114. DBG_FACILITY_RPC,
  115. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  116. _TEXT("Can't find ending mailslot name\n")
  117. );
  118. dwStatus = ERROR_INVALID_PARAMETER;
  119. break;
  120. }
  121. *ePtr = _TEXT('\0');
  122. DBGPrintf(
  123. DBG_INFORMATION,
  124. DBG_FACILITY_RPC,
  125. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  126. _TEXT("response to client %s, %s\n"),
  127. pClientName,
  128. pMailSlot
  129. );
  130. //
  131. // Do not response to "*"
  132. //
  133. if(_tcsicmp(pClientName, _TEXT("*")) == 0)
  134. {
  135. dwStatus = ERROR_INVALID_PARAMETER;
  136. break;
  137. }
  138. if (lstrlen(pClientName) + lstrlen(pMailSlot) + 13 > sizeof(szPipeName) / sizeof(TCHAR))
  139. {
  140. dwStatus = ERROR_INVALID_PARAMETER;
  141. break;
  142. }
  143. //
  144. // Open client side mailslot
  145. //
  146. wsprintf(
  147. szPipeName,
  148. _TEXT("\\\\%s\\mailslot\\%s"),
  149. pClientName,
  150. pMailSlot
  151. );
  152. hSlot = CreateFile(
  153. szPipeName,
  154. GENERIC_WRITE, // only need write
  155. FILE_SHARE_WRITE,
  156. NULL,
  157. OPEN_EXISTING,
  158. FILE_ATTRIBUTE_NORMAL,
  159. NULL
  160. );
  161. if(hSlot == INVALID_HANDLE_VALUE)
  162. {
  163. dwStatus = GetLastError();
  164. DBGPrintf(
  165. DBG_INFORMATION,
  166. DBG_FACILITY_RPC,
  167. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  168. _TEXT("CreateFile %s failed with %d\n"),
  169. szPipeName,
  170. dwStatus
  171. );
  172. break;
  173. }
  174. //
  175. // Write our computername to client side mailslot
  176. //
  177. if(!WriteFile(hSlot, szComputerName, (_tcslen(szComputerName)+1)*sizeof(TCHAR), &byteWritten, NULL) ||
  178. byteWritten != (_tcslen(szComputerName)+1)*sizeof(TCHAR) )
  179. {
  180. dwStatus = GetLastError();
  181. DBGPrintf(
  182. DBG_INFORMATION,
  183. DBG_FACILITY_RPC,
  184. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  185. _TEXT("Write to %s failed with %d\n"),
  186. szPipeName,
  187. dwStatus
  188. );
  189. }
  190. } while(FALSE);
  191. if(hSlot != INVALID_HANDLE_VALUE)
  192. {
  193. CloseHandle(hSlot);
  194. }
  195. return dwStatus;
  196. }
  197. //--------------------------------------------------------------------
  198. DWORD
  199. HandleChallenge(
  200. DWORD cbData,
  201. PBYTE pbData
  202. )
  203. /*++
  204. ++*/
  205. {
  206. return ERROR_SUCCESS;
  207. }
  208. //---------------------------------------------------------------------
  209. unsigned int WINAPI
  210. MailSlotThread(void* ptr)
  211. {
  212. HANDLE hEvent=(HANDLE) ptr;
  213. DWORD dwStatus=ERROR_SUCCESS;
  214. HANDLE hSlot=INVALID_HANDLE_VALUE;
  215. DWORD cbToRead;
  216. TCHAR szMailSlotName[MAX_PATH+1];
  217. TCHAR szMessage[MAX_MAILSLOT_MSG_SIZE+1];
  218. BOOL fResult=TRUE;
  219. do {
  220. //
  221. // Create the mail slot
  222. //
  223. wsprintf(
  224. szMailSlotName,
  225. _TEXT("\\\\.\\mailslot\\%s"),
  226. _TEXT(SERVERMAILSLOTNAME)
  227. );
  228. hSlot=CreateMailslot(
  229. szMailSlotName,
  230. MAX_MAILSLOT_MSG_SIZE,
  231. MAILSLOT_WAIT_FOREVER,
  232. NULL //&SecurityAttributes
  233. );
  234. if(hSlot == INVALID_HANDLE_VALUE)
  235. {
  236. dwStatus=GetLastError();
  237. break;
  238. }
  239. //
  240. // Signal mail thread we are ready
  241. //
  242. SetEvent(hEvent);
  243. DBGPrintf(
  244. DBG_INFORMATION,
  245. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  246. DBG_ALL_LEVEL,
  247. _TEXT("Mailslot : ready...\n")
  248. );
  249. //
  250. // Forever loop
  251. //
  252. while(dwStatus == ERROR_SUCCESS)
  253. {
  254. memset(szMessage, 0, sizeof(szMessage));
  255. //
  256. // Wait on the Slot - TODO consider using IO completion port.
  257. //
  258. fResult=ReadFile(
  259. hSlot,
  260. szMessage,
  261. sizeof(szMessage) - sizeof(TCHAR),
  262. &cbToRead,
  263. NULL
  264. );
  265. if(!fResult)
  266. {
  267. DBGPrintf(
  268. DBG_ERROR,
  269. DBG_FACILITY_RPC,
  270. DBGLEVEL_FUNCTION_ERROR,
  271. _TEXT("Mailslot : read failed %d\n"),
  272. GetLastError()
  273. );
  274. continue;
  275. }
  276. DBGPrintf(
  277. DBG_INFORMATION,
  278. DBG_FACILITY_RPC,
  279. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  280. _TEXT("Mailslot : receive message %s\n"),
  281. szMessage
  282. );
  283. //
  284. // Process Message
  285. //
  286. for(int i=0; i < dwNumProtocol; i++)
  287. {
  288. if(!_tcsnicmp(szMessage, pfm[i].szProtocol, _tcslen(pfm[i].szProtocol)))
  289. {
  290. (pfm[i].func)( ((DWORD)_tcslen(szMessage) - (DWORD)_tcslen(pfm[i].szProtocol))*sizeof(TCHAR),
  291. (PBYTE)(szMessage + _tcslen(pfm[i].szProtocol)) );
  292. }
  293. }
  294. }
  295. } while (FALSE);
  296. if(hSlot != INVALID_HANDLE_VALUE)
  297. CloseHandle(hSlot);
  298. //
  299. // Mail thread will close the event handle
  300. //
  301. ExitThread(dwStatus);
  302. return dwStatus;
  303. }
  304. //---------------------------------------------------------------------
  305. DWORD
  306. InitMailSlotThread()
  307. /*++
  308. ++*/
  309. {
  310. HANDLE hThread = NULL;
  311. unsigned int dwThreadId;
  312. HANDLE hEvent = NULL;
  313. DWORD dwStatus = ERROR_SUCCESS;
  314. HANDLE waithandles[2];
  315. //
  316. // Create a event for namedpipe thread to signal it is ready.
  317. //
  318. hEvent = CreateEvent(
  319. NULL,
  320. FALSE,
  321. FALSE, // non-signal
  322. NULL
  323. );
  324. if(hEvent == NULL)
  325. {
  326. dwStatus = GetLastError();
  327. goto cleanup;
  328. }
  329. hThread = (HANDLE)_beginthreadex(
  330. NULL,
  331. 0,
  332. MailSlotThread,
  333. hEvent,
  334. 0,
  335. &dwThreadId
  336. );
  337. if(hThread == NULL)
  338. {
  339. dwStatus = GetLastError();
  340. goto cleanup;
  341. }
  342. waithandles[0] = hEvent;
  343. waithandles[1] = hThread;
  344. //
  345. // Wait 30 second for thread to complet initialization
  346. //
  347. dwStatus = WaitForMultipleObjects(
  348. sizeof(waithandles)/sizeof(waithandles[0]),
  349. waithandles,
  350. FALSE,
  351. 30*1000
  352. );
  353. if(dwStatus == WAIT_OBJECT_0)
  354. {
  355. //
  356. // thread is ready
  357. //
  358. dwStatus = ERROR_SUCCESS;
  359. }
  360. else
  361. {
  362. if(dwStatus == (WAIT_OBJECT_0 + 1))
  363. {
  364. //
  365. // Thread terminate abnormally
  366. //
  367. GetExitCodeThread(
  368. hThread,
  369. &dwStatus
  370. );
  371. }
  372. else
  373. {
  374. dwStatus = TLS_E_SERVICE_STARTUP_CREATE_THREAD;
  375. }
  376. }
  377. cleanup:
  378. if(hEvent != NULL)
  379. {
  380. CloseHandle(hEvent);
  381. }
  382. if(hThread != NULL)
  383. {
  384. CloseHandle(hThread);
  385. }
  386. return dwStatus;
  387. }