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.

513 lines
13 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. DWORD dwFileType;
  52. if(cbData >= sizeof(szDiscMsg)-sizeof(TCHAR))
  53. {
  54. dwStatus = ERROR_INVALID_PARAMETER;
  55. return dwStatus;
  56. }
  57. //
  58. // Prevent no NULL terminated input
  59. //
  60. memset(szDiscMsg, 0, sizeof(szDiscMsg));
  61. memcpy(szDiscMsg, pbData, cbData);
  62. GetComputerName(szComputerName, &cbComputerName);
  63. do {
  64. //
  65. // Extract client machine name
  66. //
  67. pClientName=_tcschr(szDiscMsg, _TEXT(LSERVER_OPEN_BLK));
  68. if(pClientName == NULL)
  69. {
  70. DBGPrintf(
  71. DBG_INFORMATION,
  72. DBG_FACILITY_RPC,
  73. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  74. _TEXT("Can't find beginning client name\n")
  75. );
  76. dwStatus = ERROR_INVALID_PARAMETER;
  77. break;
  78. }
  79. pClientName = _tcsinc(pClientName);
  80. ePtr=_tcschr(pClientName, _TEXT(LSERVER_CLOSE_BLK));
  81. if(ePtr == NULL)
  82. {
  83. DBGPrintf(
  84. DBG_INFORMATION,
  85. DBG_FACILITY_RPC,
  86. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  87. _TEXT("Can't find ending client name\n")
  88. );
  89. dwStatus = ERROR_INVALID_PARAMETER;
  90. break;
  91. }
  92. *ePtr = _TEXT('\0');
  93. //
  94. // Extract Mailslot name
  95. //
  96. ePtr = _tcsinc(ePtr);
  97. pMailSlot = _tcschr(ePtr, _TEXT(LSERVER_OPEN_BLK));
  98. if(pMailSlot == NULL)
  99. {
  100. DBGPrintf(
  101. DBG_INFORMATION,
  102. DBG_FACILITY_RPC,
  103. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  104. _TEXT("Can't find beginning mailslot name\n")
  105. );
  106. dwStatus = ERROR_INVALID_PARAMETER;
  107. break;
  108. }
  109. pMailSlot = _tcsinc(pMailSlot);
  110. ePtr=_tcschr(pMailSlot, _TEXT(LSERVER_CLOSE_BLK));
  111. if(ePtr == NULL)
  112. {
  113. DBGPrintf(
  114. DBG_INFORMATION,
  115. DBG_FACILITY_RPC,
  116. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  117. _TEXT("Can't find ending mailslot name\n")
  118. );
  119. dwStatus = ERROR_INVALID_PARAMETER;
  120. break;
  121. }
  122. *ePtr = _TEXT('\0');
  123. DBGPrintf(
  124. DBG_INFORMATION,
  125. DBG_FACILITY_RPC,
  126. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  127. _TEXT("response to client %s, %s\n"),
  128. pClientName,
  129. pMailSlot
  130. );
  131. //
  132. // Do not respond to "*"
  133. //
  134. if(_tcscmp(pClientName, _TEXT("*")) == 0)
  135. {
  136. dwStatus = ERROR_INVALID_PARAMETER;
  137. break;
  138. }
  139. if (lstrlen(pClientName) + lstrlen(pMailSlot) + 13 > sizeof(szPipeName) / sizeof(TCHAR))
  140. {
  141. dwStatus = ERROR_INVALID_PARAMETER;
  142. break;
  143. }
  144. //
  145. // SECURITY: Must make sure that what we're opening is really a
  146. // mailslot (no tricks with .., extra backslashes, etc.
  147. //
  148. if ((_tcsstr(pClientName,_TEXT("..")) != NULL)
  149. || (_tcsstr(pMailSlot,_TEXT("..")) != NULL))
  150. {
  151. dwStatus = ERROR_INVALID_PARAMETER;
  152. break;
  153. }
  154. if ((_tcschr(pClientName, _TEXT('\\')) != NULL)
  155. || (_tcschr(pMailSlot, _TEXT('\\')) != NULL))
  156. {
  157. dwStatus = ERROR_INVALID_PARAMETER;
  158. break;
  159. }
  160. //
  161. // Open client side mailslot
  162. //
  163. wsprintf(
  164. szPipeName,
  165. _TEXT("\\\\%s\\mailslot\\%s"),
  166. pClientName,
  167. pMailSlot
  168. );
  169. if (0 == ImpersonateAnonymousToken(GetCurrentThread()))
  170. {
  171. dwStatus = GetLastError();
  172. break;
  173. }
  174. hSlot = CreateFile(
  175. szPipeName,
  176. GENERIC_WRITE, // only need write
  177. FILE_SHARE_WRITE,
  178. NULL,
  179. OPEN_EXISTING,
  180. FILE_ATTRIBUTE_NORMAL,
  181. NULL
  182. );
  183. if(hSlot == INVALID_HANDLE_VALUE)
  184. {
  185. dwStatus = GetLastError();
  186. RevertToSelf();
  187. DBGPrintf(
  188. DBG_INFORMATION,
  189. DBG_FACILITY_RPC,
  190. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  191. _TEXT("CreateFile %s failed with %d\n"),
  192. szPipeName,
  193. dwStatus
  194. );
  195. break;
  196. }
  197. dwFileType = GetFileType(hSlot);
  198. if ((FILE_TYPE_DISK == dwFileType)
  199. || (FILE_TYPE_CHAR == dwFileType)
  200. || (FILE_TYPE_PIPE == dwFileType))
  201. {
  202. //
  203. // This isn't a mailslot!
  204. //
  205. RevertToSelf();
  206. dwStatus = ERROR_INVALID_PARAMETER;
  207. break;
  208. }
  209. //
  210. // Write our computername to client side mailslot
  211. //
  212. if(!WriteFile(hSlot, szComputerName, (_tcslen(szComputerName)+1)*sizeof(TCHAR), &byteWritten, NULL) ||
  213. byteWritten != (_tcslen(szComputerName)+1)*sizeof(TCHAR) )
  214. {
  215. dwStatus = GetLastError();
  216. RevertToSelf();
  217. DBGPrintf(
  218. DBG_INFORMATION,
  219. DBG_FACILITY_RPC,
  220. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  221. _TEXT("Write to %s failed with %d\n"),
  222. szPipeName,
  223. dwStatus
  224. );
  225. break;
  226. }
  227. RevertToSelf();
  228. } while(FALSE);
  229. if(hSlot != INVALID_HANDLE_VALUE)
  230. {
  231. CloseHandle(hSlot);
  232. }
  233. return dwStatus;
  234. }
  235. //--------------------------------------------------------------------
  236. DWORD
  237. HandleChallenge(
  238. DWORD cbData,
  239. PBYTE pbData
  240. )
  241. /*++
  242. ++*/
  243. {
  244. return ERROR_SUCCESS;
  245. }
  246. //---------------------------------------------------------------------
  247. unsigned int WINAPI
  248. MailSlotThread(void* ptr)
  249. {
  250. HANDLE hEvent=(HANDLE) ptr;
  251. DWORD dwStatus=ERROR_SUCCESS;
  252. HANDLE hSlot=INVALID_HANDLE_VALUE;
  253. DWORD cbToRead;
  254. TCHAR szMailSlotName[MAX_PATH+1];
  255. TCHAR szMessage[MAX_MAILSLOT_MSG_SIZE+1];
  256. BOOL fResult=TRUE;
  257. do {
  258. //
  259. // Create the mail slot
  260. //
  261. wsprintf(
  262. szMailSlotName,
  263. _TEXT("\\\\.\\mailslot\\%s"),
  264. _TEXT(SERVERMAILSLOTNAME)
  265. );
  266. hSlot=CreateMailslot(
  267. szMailSlotName,
  268. MAX_MAILSLOT_MSG_SIZE,
  269. MAILSLOT_WAIT_FOREVER,
  270. NULL //&SecurityAttributes
  271. );
  272. if(hSlot == INVALID_HANDLE_VALUE)
  273. {
  274. dwStatus=GetLastError();
  275. break;
  276. }
  277. //
  278. // Signal mail thread we are ready
  279. //
  280. SetEvent(hEvent);
  281. DBGPrintf(
  282. DBG_INFORMATION,
  283. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  284. DBG_ALL_LEVEL,
  285. _TEXT("Mailslot : ready...\n")
  286. );
  287. //
  288. // Forever loop
  289. //
  290. while(dwStatus == ERROR_SUCCESS)
  291. {
  292. memset(szMessage, 0, sizeof(szMessage));
  293. //
  294. // Wait on the Slot - TODO consider using IO completion port.
  295. //
  296. fResult=ReadFile(
  297. hSlot,
  298. szMessage,
  299. sizeof(szMessage) - sizeof(TCHAR),
  300. &cbToRead,
  301. NULL
  302. );
  303. if(!fResult)
  304. {
  305. DBGPrintf(
  306. DBG_ERROR,
  307. DBG_FACILITY_RPC,
  308. DBGLEVEL_FUNCTION_ERROR,
  309. _TEXT("Mailslot : read failed %d\n"),
  310. GetLastError()
  311. );
  312. continue;
  313. }
  314. DBGPrintf(
  315. DBG_INFORMATION,
  316. DBG_FACILITY_RPC,
  317. DBGLEVEL_FUNCTION_DETAILSIMPLE,
  318. _TEXT("Mailslot : receive message %s\n"),
  319. szMessage
  320. );
  321. //
  322. // Process Message
  323. //
  324. for(int i=0; i < dwNumProtocol; i++)
  325. {
  326. if(!_tcsnicmp(szMessage, pfm[i].szProtocol, _tcslen(pfm[i].szProtocol)))
  327. {
  328. (pfm[i].func)( ((DWORD)_tcslen(szMessage) - (DWORD)_tcslen(pfm[i].szProtocol))*sizeof(TCHAR),
  329. (PBYTE)(szMessage + _tcslen(pfm[i].szProtocol)) );
  330. }
  331. }
  332. }
  333. } while (FALSE);
  334. if(hSlot != INVALID_HANDLE_VALUE)
  335. CloseHandle(hSlot);
  336. //
  337. // Mail thread will close the event handle
  338. //
  339. ExitThread(dwStatus);
  340. return dwStatus;
  341. }
  342. //---------------------------------------------------------------------
  343. DWORD
  344. InitMailSlotThread()
  345. /*++
  346. ++*/
  347. {
  348. HANDLE hThread = NULL;
  349. unsigned int dwThreadId;
  350. HANDLE hEvent = NULL;
  351. DWORD dwStatus = ERROR_SUCCESS;
  352. HANDLE waithandles[2];
  353. //
  354. // Create a event for namedpipe thread to signal it is ready.
  355. //
  356. hEvent = CreateEvent(
  357. NULL,
  358. FALSE,
  359. FALSE, // non-signal
  360. NULL
  361. );
  362. if(hEvent == NULL)
  363. {
  364. dwStatus = GetLastError();
  365. goto cleanup;
  366. }
  367. hThread = (HANDLE)_beginthreadex(
  368. NULL,
  369. 0,
  370. MailSlotThread,
  371. hEvent,
  372. 0,
  373. &dwThreadId
  374. );
  375. if(hThread == NULL)
  376. {
  377. dwStatus = GetLastError();
  378. goto cleanup;
  379. }
  380. waithandles[0] = hEvent;
  381. waithandles[1] = hThread;
  382. //
  383. // Wait 30 second for thread to complet initialization
  384. //
  385. dwStatus = WaitForMultipleObjects(
  386. sizeof(waithandles)/sizeof(waithandles[0]),
  387. waithandles,
  388. FALSE,
  389. 30*1000
  390. );
  391. if(dwStatus == WAIT_OBJECT_0)
  392. {
  393. //
  394. // thread is ready
  395. //
  396. dwStatus = ERROR_SUCCESS;
  397. }
  398. else
  399. {
  400. if(dwStatus == (WAIT_OBJECT_0 + 1))
  401. {
  402. //
  403. // Thread terminate abnormally
  404. //
  405. GetExitCodeThread(
  406. hThread,
  407. &dwStatus
  408. );
  409. }
  410. else
  411. {
  412. dwStatus = TLS_E_SERVICE_STARTUP_CREATE_THREAD;
  413. }
  414. }
  415. cleanup:
  416. if(hEvent != NULL)
  417. {
  418. CloseHandle(hEvent);
  419. }
  420. if(hThread != NULL)
  421. {
  422. CloseHandle(hThread);
  423. }
  424. return dwStatus;
  425. }