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.

192 lines
6.1 KiB

  1. #include <precomp.h>
  2. #include "tracing.h"
  3. #include "utils.h"
  4. #include "intflist.h"
  5. #include "intfhdl.h"
  6. DWORD
  7. OpenIntfHandle(
  8. LPWSTR wszGuid,
  9. PHANDLE pIntfHdl)
  10. {
  11. DWORD dwErr;
  12. PHASH_NODE pNode;
  13. PHSH_HANDLE pHshHandle;
  14. DbgPrint((TRC_TRACK,"[OpenIntfHandle(%S)", wszGuid));
  15. // the caller is supposed to expect the handle in return
  16. // if he doesn't, return with INVALID_PARAMETER.
  17. if (pIntfHdl == NULL)
  18. {
  19. dwErr = ERROR_INVALID_PARAMETER;
  20. goto exit;
  21. }
  22. // lock the hash, to mutual exclude concurrent calls
  23. EnterCriticalSection(&g_hshHandles.csMutex);
  24. // query the hash for the guid.
  25. dwErr = HshQueryObjectRef(
  26. g_hshHandles.pRoot,
  27. wszGuid,
  28. &pNode);
  29. // if the guid in the hash, we already have the handle opened..
  30. if (dwErr == ERROR_SUCCESS)
  31. {
  32. // return it to the caller and bump up the reference counter.
  33. // the caller is still supposed to close this handle when it is
  34. // no longer needed
  35. pHshHandle = (PHSH_HANDLE)pNode->pObject;
  36. pHshHandle->nRefCount++;
  37. *pIntfHdl = pHshHandle->hdlInterf;
  38. DbgPrint((TRC_GENERIC, "OpenIntfHandle -> 0x%x (cached)", *pIntfHdl));
  39. }
  40. // if the guid is not in the hash, we need to open a new handle for
  41. // this guid.
  42. else if (dwErr == ERROR_FILE_NOT_FOUND)
  43. {
  44. HANDLE IntfHdl = INVALID_HANDLE_VALUE;
  45. DWORD dwDummy;
  46. dwErr = ERROR_SUCCESS;
  47. // first allocate memory for the HSH_HANDLE object.
  48. // if this fails no need to go further to ndisuio
  49. pHshHandle = MemCAlloc(sizeof(HSH_HANDLE));
  50. if (pHshHandle == NULL)
  51. dwErr = GetLastError();
  52. // if everything looks fine so far
  53. if (dwErr == ERROR_SUCCESS)
  54. {
  55. // create the handle
  56. IntfHdl = CreateFileA(
  57. "\\\\.\\\\Ndisuio",
  58. GENERIC_READ | GENERIC_WRITE,
  59. FILE_SHARE_READ | FILE_SHARE_WRITE,
  60. NULL,
  61. OPEN_EXISTING,
  62. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  63. INVALID_HANDLE_VALUE);
  64. if (IntfHdl == INVALID_HANDLE_VALUE)
  65. {
  66. dwErr = GetLastError();
  67. DbgPrint((TRC_ERR,"CreateFileA failed with %d", dwErr));
  68. }
  69. }
  70. // if still fine so far
  71. if (dwErr == ERROR_SUCCESS)
  72. {
  73. // attempt to open the handle
  74. if (!DeviceIoControl(
  75. IntfHdl,
  76. IOCTL_NDISUIO_OPEN_DEVICE,
  77. (LPVOID)wszGuid,
  78. wcslen(wszGuid)*sizeof(WCHAR),
  79. NULL,
  80. 0,
  81. &dwDummy,
  82. NULL))
  83. {
  84. dwErr = GetLastError();
  85. DbgPrint((TRC_ERR,"IOCTL_NDISUIO_OPEN_DEVICE failed with %d", dwErr));
  86. }
  87. }
  88. // if finally we're ok here,
  89. if (dwErr == ERROR_SUCCESS)
  90. {
  91. // set up the HSH_HANDLE structure and insert it in the hash
  92. pHshHandle->hdlInterf = IntfHdl;
  93. pHshHandle->nRefCount = 1;
  94. dwErr = HshInsertObjectRef(
  95. g_hshHandles.pRoot,
  96. wszGuid,
  97. pHshHandle,
  98. &g_hshHandles.pRoot);
  99. }
  100. // if ok at the end, return the handle to the caller
  101. if (dwErr == ERROR_SUCCESS)
  102. {
  103. DbgPrint((TRC_GENERIC, "OpenIntfHandle -> 0x%x (new)", IntfHdl));
  104. *pIntfHdl = IntfHdl;
  105. }
  106. // otherwise clear up all resources
  107. else
  108. {
  109. if (IntfHdl != INVALID_HANDLE_VALUE)
  110. CloseHandle(IntfHdl);
  111. MemFree(pHshHandle);
  112. }
  113. }
  114. // out of critical section
  115. LeaveCriticalSection(&g_hshHandles.csMutex);
  116. exit:
  117. DbgPrint((TRC_TRACK,"OpenIntfHandle]=%d", dwErr));
  118. return dwErr;
  119. }
  120. DWORD
  121. CloseIntfHandle(
  122. LPWSTR wszGuid)
  123. {
  124. DWORD dwErr;
  125. PHASH_NODE pNode;
  126. DbgPrint((TRC_TRACK,"[CloseIntfHandle(%S)", wszGuid));
  127. // lock the hash
  128. EnterCriticalSection(&g_hshHandles.csMutex);
  129. // query the hash for the guid.
  130. dwErr = HshQueryObjectRef(
  131. g_hshHandles.pRoot,
  132. wszGuid,
  133. &pNode);
  134. // the object should be found.. but who knows
  135. if (dwErr == ERROR_SUCCESS)
  136. {
  137. PHSH_HANDLE pHshHandle;
  138. // the hash refuses to hash in NULL pObjects, so pHshHandle is guaranteed to be not NULL
  139. pHshHandle = (PHSH_HANDLE)pNode->pObject;
  140. // HshHandles are hashed in with a refCount of 1, and whenever we remove a handle
  141. // if the ref count reaches 0 we delete it entirely.
  142. // Having here a <=0 ref count is completely wrong.
  143. DbgAssert((pHshHandle->nRefCount > 0, "Corrupted nRefCount %d", pHshHandle->nRefCount));
  144. pHshHandle->nRefCount--;
  145. // if the ref count reached 0, remove the HSH_HANDLE from the hash..
  146. if (pHshHandle->nRefCount == 0)
  147. {
  148. dwErr = HshRemoveObjectRef(
  149. g_hshHandles.pRoot,
  150. pNode,
  151. &pHshHandle,
  152. &g_hshHandles.pRoot);
  153. if (dwErr == ERROR_SUCCESS)
  154. {
  155. // .. and clear all associated resources
  156. DbgPrint((TRC_GENERIC,"CloseIntfHandle -> 0x%x (closed)", pHshHandle->hdlInterf));
  157. CloseHandle(pHshHandle->hdlInterf);
  158. MemFree(pHshHandle);
  159. }
  160. }
  161. else
  162. {
  163. DbgPrint((TRC_GENERIC,"CloseIntfHandle -> 0x%x (deref)", pHshHandle->hdlInterf));
  164. }
  165. }
  166. LeaveCriticalSection(&g_hshHandles.csMutex);
  167. DbgPrint((TRC_TRACK,"CloseIntfHandle]=%d", dwErr));
  168. return dwErr;
  169. }