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.

420 lines
11 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. handle.c
  5. Abstract:
  6. This module contains the handle table mgmt routines.
  7. Author:
  8. Wesley Witt (wesw) 12-Nov-1996
  9. Revision History:
  10. --*/
  11. #include "faxsvc.h"
  12. #pragma hdrstop
  13. LIST_ENTRY g_HandleTableListHead;
  14. CFaxCriticalSection g_CsHandleTable;
  15. void
  16. FreeServiceContextHandles(
  17. void
  18. )
  19. {
  20. PLIST_ENTRY Next;
  21. PHANDLE_ENTRY pHandleEntry;
  22. Next = g_HandleTableListHead.Flink;
  23. while ((ULONG_PTR)Next != (ULONG_PTR)&g_HandleTableListHead)
  24. {
  25. pHandleEntry = CONTAINING_RECORD( Next, HANDLE_ENTRY, ListEntry );
  26. Next = pHandleEntry->ListEntry.Flink;
  27. CloseFaxHandle (pHandleEntry);
  28. }
  29. return;
  30. }
  31. static
  32. PHANDLE_ENTRY
  33. CreateNewHandle(
  34. handle_t hBinding,
  35. FaxHandleType Type,
  36. DWORD dwClientAPIVersion, // Used for connection handles
  37. PLINE_INFO LineInfo, // Used for port handles
  38. DWORD Flags // Used for port handles
  39. )
  40. {
  41. PHANDLE_ENTRY pHandleEntry;
  42. pHandleEntry = (PHANDLE_ENTRY) MemAlloc( sizeof(HANDLE_ENTRY) );
  43. if (!pHandleEntry)
  44. {
  45. return NULL;
  46. }
  47. ZeroMemory (pHandleEntry, sizeof(HANDLE_ENTRY));
  48. pHandleEntry->hBinding = hBinding;
  49. pHandleEntry->Type = Type;
  50. pHandleEntry->dwClientAPIVersion = dwClientAPIVersion;
  51. pHandleEntry->LineInfo = LineInfo;
  52. pHandleEntry->Flags = Flags;
  53. pHandleEntry->bReleased = FALSE;
  54. pHandleEntry->hFile = INVALID_HANDLE_VALUE;
  55. EnterCriticalSection( &g_CsHandleTable );
  56. InsertTailList( &g_HandleTableListHead, &pHandleEntry->ListEntry );
  57. LeaveCriticalSection( &g_CsHandleTable );
  58. return pHandleEntry;
  59. }
  60. PHANDLE_ENTRY
  61. CreateNewConnectionHandle(
  62. handle_t hBinding,
  63. DWORD dwClientAPIVersion
  64. )
  65. {
  66. return CreateNewHandle(
  67. hBinding,
  68. FHT_SERVICE,
  69. dwClientAPIVersion,
  70. NULL, // Unused
  71. 0 // Unused
  72. );
  73. }
  74. PHANDLE_ENTRY
  75. CreateNewPortHandle(
  76. handle_t hBinding,
  77. PLINE_INFO LineInfo,
  78. DWORD Flags
  79. )
  80. {
  81. return CreateNewHandle(
  82. hBinding,
  83. FHT_PORT,
  84. 0, // Unused
  85. LineInfo,
  86. Flags
  87. );
  88. }
  89. PHANDLE_ENTRY
  90. CreateNewMsgEnumHandle(
  91. handle_t hBinding,
  92. HANDLE hFileFind,
  93. LPCWSTR lpcwstrFirstFileName,
  94. FAX_ENUM_MESSAGE_FOLDER Folder
  95. )
  96. /*++
  97. Routine name : CreateNewMsgEnumHandle
  98. Routine description:
  99. Creates a new context handle for messages enumeration
  100. Author:
  101. Eran Yariv (EranY), Dec, 1999
  102. Arguments:
  103. hBinding [in] - RPC Binding handle
  104. hFileFind [in] - Find file handle
  105. lpcwstrFirstFileName [in] - Name of first file found
  106. Folder [in] - Archive folder type of find file search
  107. Return Value:
  108. Returns a pointer to a newly created handle
  109. --*/
  110. {
  111. DEBUG_FUNCTION_NAME(TEXT("CreateNewMsgEnumHandle"));
  112. Assert (INVALID_HANDLE_VALUE != hFileFind);
  113. if (MAX_PATH <= lstrlen (lpcwstrFirstFileName))
  114. {
  115. DebugPrintEx(
  116. DEBUG_ERR,
  117. TEXT("String passed is too long (%s)"),
  118. lpcwstrFirstFileName);
  119. ASSERT_FALSE;
  120. return NULL;
  121. }
  122. PHANDLE_ENTRY pHandle = CreateNewHandle (hBinding,
  123. FHT_MSGENUM,
  124. FindClientAPIVersion(hBinding), // Client API version
  125. NULL, // Unused
  126. 0); // Unused
  127. if (!pHandle)
  128. {
  129. DebugPrintEx(
  130. DEBUG_ERR,
  131. TEXT("CreateNewHandle failed"));
  132. return NULL;
  133. }
  134. //
  135. // Store find file handle and first file in the new context
  136. //
  137. pHandle->hFile = hFileFind;
  138. wcsncpy (pHandle->wstrFileName, lpcwstrFirstFileName, ARR_SIZE(pHandle->wstrFileName)-1);
  139. pHandle->Folder = Folder;
  140. return pHandle;
  141. } // CreateNewMsgEnumHandle
  142. PHANDLE_ENTRY
  143. CreateNewCopyHandle(
  144. handle_t hBinding,
  145. HANDLE hFile,
  146. BOOL bCopyToServer,
  147. LPCWSTR lpcwstrFileName,
  148. PJOB_QUEUE pJobQueue
  149. )
  150. /*++
  151. Routine name : CreateNewCopyHandle
  152. Routine description:
  153. Creates a new context handle for RPC copy
  154. Author:
  155. Eran Yariv (EranY), Dec, 1999
  156. Arguments:
  157. hBinding [in] - RPC Binding handle
  158. hFileFind [in] - File handle
  159. bCopyToServer [in] - Copy direction
  160. lpcwstrFileName [in] - Name of file generated on the server
  161. (in use for rundown purposes only if bCopyToServer is TRUE)
  162. pJobQueue [in] - Pointer to the job queue containing thr preview file
  163. (in use for rundown purposes only if bCopyToServer is FALSE)
  164. Return Value:
  165. Returns a pointer to a newly created handle
  166. --*/
  167. {
  168. DEBUG_FUNCTION_NAME(TEXT("CreateNewCopyHandle"));
  169. Assert (INVALID_HANDLE_VALUE != hFile);
  170. PHANDLE_ENTRY pHandle = CreateNewHandle (hBinding,
  171. FHT_COPY,
  172. 0, // Unused
  173. NULL, // Unused
  174. 0); // Unused
  175. if (!pHandle)
  176. {
  177. DebugPrintEx(
  178. DEBUG_ERR,
  179. TEXT("CreateNewHandle failed"));
  180. return NULL;
  181. }
  182. //
  183. // Store file handle and direction in the new context
  184. //
  185. pHandle->hFile = hFile;
  186. pHandle->bCopyToServer = bCopyToServer;
  187. pHandle->bError = FALSE;
  188. if (bCopyToServer)
  189. {
  190. //
  191. // If this is a copy operation to the server, we keep the name of the file
  192. // created in the server's queue so that in the rundown operation we can delete this file.
  193. //
  194. Assert (lstrlen (lpcwstrFileName) < MAX_PATH); //wstrFileName is MAX_PATH size
  195. wcsncpy (pHandle->wstrFileName, lpcwstrFileName, ARR_SIZE(pHandle->wstrFileName)-1);
  196. }
  197. else
  198. {
  199. pHandle->pJobQueue = pJobQueue;
  200. }
  201. return pHandle;
  202. } // CreateNewCopyHandle
  203. VOID
  204. CloseFaxHandle(
  205. PHANDLE_ENTRY pHandleEntry
  206. )
  207. {
  208. //
  209. // note that the HandleEntry may be a context handle,
  210. // which may be NULL in some cases. Do nothing if
  211. // this is the case
  212. //
  213. DEBUG_FUNCTION_NAME(TEXT("CloseFaxHandle"));
  214. Assert (pHandleEntry);
  215. EnterCriticalSection( &g_CsHandleTable );
  216. RemoveEntryList( &pHandleEntry->ListEntry );
  217. if ((pHandleEntry->Type == FHT_SERVICE) && !(pHandleEntry->bReleased))
  218. {
  219. SafeDecIdleCounter (&g_dwConnectionCount);
  220. }
  221. else if (pHandleEntry->Type == FHT_MSGENUM)
  222. {
  223. if (!FindClose (pHandleEntry->hFile))
  224. {
  225. DebugPrintEx( DEBUG_ERR,
  226. TEXT("FindClose returned error code %ld"),
  227. GetLastError());
  228. }
  229. }
  230. else if (pHandleEntry->Type == FHT_COPY)
  231. {
  232. if (!CloseHandle (pHandleEntry->hFile))
  233. {
  234. DebugPrintEx( DEBUG_ERR,
  235. TEXT("CloseHandle returned error code %ld"),
  236. GetLastError());
  237. }
  238. if (pHandleEntry->bError && pHandleEntry->bCopyToServer)
  239. {
  240. //
  241. // We found an error while copying to the server.
  242. // Remove temporary file created in the server's queue
  243. //
  244. if (!DeleteFile (pHandleEntry->wstrFileName))
  245. {
  246. DWORD dwRes = GetLastError ();
  247. DebugPrintEx( DEBUG_ERR,
  248. TEXT("DeleteFile (%s) returned error code %ld"),
  249. pHandleEntry->wstrFileName,
  250. dwRes);
  251. }
  252. }
  253. if (FALSE == pHandleEntry->bCopyToServer)
  254. {
  255. if (pHandleEntry->pJobQueue)
  256. {
  257. //
  258. // Decrease ref count only for queued jobs
  259. //
  260. EnterCriticalSection (&g_CsQueue);
  261. DecreaseJobRefCount (pHandleEntry->pJobQueue, TRUE, TRUE, TRUE);
  262. LeaveCriticalSection (&g_CsQueue);
  263. }
  264. }
  265. }
  266. MemFree( pHandleEntry );
  267. LeaveCriticalSection( &g_CsHandleTable );
  268. }
  269. BOOL
  270. IsPortOpenedForModify(
  271. PLINE_INFO LineInfo
  272. )
  273. {
  274. PLIST_ENTRY Next;
  275. PHANDLE_ENTRY HandleEntry;
  276. EnterCriticalSection( &g_CsHandleTable );
  277. Next = g_HandleTableListHead.Flink;
  278. if (Next == NULL)
  279. {
  280. LeaveCriticalSection( &g_CsHandleTable );
  281. return FALSE;
  282. }
  283. while ((ULONG_PTR)Next != (ULONG_PTR)&g_HandleTableListHead) {
  284. HandleEntry = CONTAINING_RECORD( Next, HANDLE_ENTRY, ListEntry );
  285. if (HandleEntry->Type == FHT_PORT && (HandleEntry->Flags & PORT_OPEN_MODIFY) && HandleEntry->LineInfo == LineInfo)
  286. {
  287. LeaveCriticalSection( &g_CsHandleTable );
  288. return TRUE;
  289. }
  290. Next = HandleEntry->ListEntry.Flink;
  291. }
  292. LeaveCriticalSection( &g_CsHandleTable );
  293. return FALSE;
  294. }
  295. DWORD
  296. FindClientAPIVersion (
  297. handle_t hFaxHandle
  298. )
  299. /*++
  300. Routine name : FindClientAPIVersion
  301. Routine description:
  302. Finds the API version of a connected client by its RPC binding handle
  303. Author:
  304. Eran Yariv (EranY), Mar, 2001
  305. Arguments:
  306. hFaxHandle [in] - RPC binding handle
  307. Return Value:
  308. Client API version
  309. --*/
  310. {
  311. PLIST_ENTRY pNext;
  312. DEBUG_FUNCTION_NAME(TEXT("FindClientAPIVersion"));
  313. EnterCriticalSection (&g_CsHandleTable);
  314. pNext = g_HandleTableListHead.Flink;
  315. if (pNext == NULL)
  316. {
  317. ASSERT_FALSE;
  318. DebugPrintEx( DEBUG_ERR,
  319. TEXT("g_CsHandleTable is corrupted"));
  320. LeaveCriticalSection (&g_CsHandleTable);
  321. return FAX_API_VERSION_0;
  322. }
  323. while ((ULONG_PTR)pNext != (ULONG_PTR)&g_HandleTableListHead)
  324. {
  325. PHANDLE_ENTRY pHandleEntry = CONTAINING_RECORD(pNext, HANDLE_ENTRY, ListEntry);
  326. if ( ((FHT_SERVICE == pHandleEntry->Type) || (FHT_MSGENUM == pHandleEntry->Type) ) &&
  327. (pHandleEntry->hBinding == hFaxHandle)
  328. )
  329. {
  330. DWORD dwRes = pHandleEntry->dwClientAPIVersion;
  331. LeaveCriticalSection (&g_CsHandleTable);
  332. return dwRes;
  333. }
  334. pNext = pHandleEntry->ListEntry.Flink;
  335. }
  336. LeaveCriticalSection (&g_CsHandleTable);
  337. DebugPrintEx( DEBUG_ERR,
  338. TEXT("No matching client entry for binding handle %08p"),
  339. hFaxHandle);
  340. return FAX_API_VERSION_0;
  341. } // FindClientAPIVersion