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.

592 lines
11 KiB

  1. #include "std.h"
  2. // {6249D949-5263-4d6a-883C-78EFAF85D5E3}
  3. static const GUID g_lhcHandleGUID =
  4. {
  5. // This guid will be used to identify LCHHANDLE structures to
  6. // help prevent accessing invalid items
  7. 0x6249d949, 0x5263, 0x4d6a,
  8. {
  9. 0x88, 0x3c, 0x78, 0xef, 0xaf, 0x85, 0xd5, 0xe3
  10. }
  11. };
  12. // {40A71300-B2C7-4d4f-808F-52643110B329}
  13. static const GUID g_lhcLibraryGUID =
  14. {
  15. // This guid will be used to identify LIBRARY_NODE structures to
  16. // help prevent accessing invalid items
  17. 0x40a71300, 0xb2c7, 0x4d4f,
  18. {
  19. 0x80, 0x8f, 0x52, 0x64, 0x31, 0x10, 0xb3, 0x29
  20. }
  21. };
  22. PLIBRARY_NODE g_pLibraryList = NULL;
  23. PLHCSTRUCT g_pObjectList = NULL;
  24. CRITICAL_SECTION g_csTableControl;
  25. BOOL lhcpIsValidHandle(PLHCSTRUCT pObject);
  26. PLIBRARY_NODE lhcpNewLibraryNode();
  27. void lhcpFreeLibraryNode(PLIBRARY_NODE pNode);
  28. PLHCSTRUCT lhcpNewObjectHandle();
  29. void lhcpFreeObjectHandle(PLHCSTRUCT pNode);
  30. BOOL lhcpIsValidHandle(PLHCSTRUCT pObject);
  31. PWSTR lhcpGetExeDirectory();
  32. PLHCSTRUCT lhcpCreateHandle(
  33. PLIBRARY_DESCRIPTOR pLibrary,
  34. PLHCOBJECT_DESCRIPTOR pObject);
  35. void lhcpDestroyHandle(PLHCSTRUCT pNode);
  36. BOOL lhcpIsValidHandle(PLHCSTRUCT pObject)
  37. {
  38. BOOL bResult;
  39. __try
  40. {
  41. bResult = IsEqualGUID(
  42. &g_lhcHandleGUID,
  43. &pObject->m_Secret);
  44. }
  45. __except(EXCEPTION_EXECUTE_HANDLER)
  46. {
  47. SetLastError(
  48. ERROR_INVALID_HANDLE);
  49. bResult = FALSE;
  50. goto Done;
  51. }
  52. Done:
  53. return bResult;
  54. }
  55. PLIBRARY_NODE lhcpNewLibraryNode()
  56. {
  57. //
  58. // Create the new node, zero out the memory and copy in the secret
  59. //
  60. PLIBRARY_NODE pNode = malloc(
  61. sizeof(LIBRARY_NODE));
  62. if (pNode!=NULL)
  63. {
  64. ZeroMemory(
  65. pNode,
  66. sizeof(LIBRARY_NODE));
  67. CopyMemory(
  68. &pNode->m_Secret,
  69. &g_lhcLibraryGUID,
  70. sizeof(GUID));
  71. }
  72. return pNode;
  73. }
  74. void lhcpFreeLibraryNode(PLIBRARY_NODE pNode)
  75. {
  76. ZeroMemory(
  77. pNode,
  78. sizeof(LIBRARY_NODE));
  79. free(
  80. pNode);
  81. }
  82. PLHCSTRUCT lhcpNewObjectHandle()
  83. {
  84. //
  85. // Create the new node, zero out the memory and copy in the secret
  86. //
  87. PLHCSTRUCT pNode = malloc(
  88. sizeof(LHCSTRUCT));
  89. if (pNode!=NULL)
  90. {
  91. ZeroMemory(
  92. pNode,
  93. sizeof(LHCSTRUCT));
  94. CopyMemory(
  95. &pNode->m_Secret,
  96. &g_lhcHandleGUID,
  97. sizeof(GUID));
  98. }
  99. return pNode;
  100. }
  101. void lhcpFreeObjectHandle(PLHCSTRUCT pNode)
  102. {
  103. ZeroMemory(
  104. pNode,
  105. sizeof(LHCSTRUCT));
  106. free(
  107. pNode);
  108. }
  109. PWSTR lhcpGetExeDirectory()
  110. {
  111. DWORD dwSize = 64;
  112. PWSTR pszBuffer = NULL;
  113. PWSTR pszReturn;
  114. DWORD dwResult;
  115. BOOL bResult;
  116. PWSTR pszLastBackslash;
  117. do
  118. {
  119. pszBuffer = malloc(
  120. dwSize * sizeof(WCHAR));
  121. if (NULL==pszBuffer)
  122. {
  123. SetLastError(
  124. ERROR_NOT_ENOUGH_MEMORY);
  125. goto Error;
  126. }
  127. dwResult = GetModuleFileNameW(
  128. NULL,
  129. pszBuffer,
  130. dwSize);
  131. if (0==dwResult)
  132. {
  133. goto Error;
  134. }
  135. if (dwSize==dwResult) // INSUFFICIENT_BUFFER
  136. {
  137. dwSize *= 2; // Double the buffer length
  138. free(
  139. pszBuffer);
  140. pszBuffer = NULL;
  141. dwResult = 0;
  142. }
  143. } while (0==dwResult && dwSize<=65536);
  144. if (dwSize>65536)
  145. {
  146. SetLastError(
  147. ERROR_INSUFFICIENT_BUFFER);
  148. goto Error;
  149. }
  150. pszLastBackslash = wcsrchr(
  151. pszBuffer,
  152. L'\\');
  153. if (NULL==pszLastBackslash)
  154. {
  155. SetLastError(
  156. ERROR_GEN_FAILURE);
  157. goto Error;
  158. }
  159. pszLastBackslash++;
  160. *pszLastBackslash = L'\0';
  161. pszReturn = malloc(
  162. (wcslen(pszBuffer)+MAX_PATH+1)*sizeof(WCHAR));
  163. if (NULL==pszReturn)
  164. {
  165. SetLastError(
  166. ERROR_NOT_ENOUGH_MEMORY);
  167. goto Error;
  168. }
  169. wcscpy(
  170. pszReturn,
  171. pszBuffer);
  172. free(
  173. pszBuffer);
  174. return pszReturn;
  175. Error:
  176. if (pszBuffer!=NULL)
  177. {
  178. free(
  179. pszBuffer);
  180. }
  181. return NULL;
  182. }
  183. PLHCSTRUCT lhcpCreateHandle(
  184. PLIBRARY_DESCRIPTOR pLibrary,
  185. PLHCOBJECT_DESCRIPTOR pObject)
  186. {
  187. PLHCSTRUCT pNode = lhcpNewObjectHandle();
  188. if (pNode!=NULL)
  189. {
  190. EnterCriticalSection(
  191. &g_csTableControl);
  192. pNode->m_pObject = pObject;
  193. pNode->m_pLibrary = pLibrary;
  194. pNode->m_pNext = g_pObjectList;
  195. pNode->m_ppThis = &g_pObjectList;
  196. if (pNode->m_pNext!=NULL)
  197. {
  198. pNode->m_pNext->m_ppThis = &pNode->m_pNext;
  199. }
  200. g_pObjectList = pNode;
  201. LeaveCriticalSection(
  202. &g_csTableControl);
  203. }
  204. else
  205. {
  206. SetLastError(
  207. ERROR_NOT_ENOUGH_MEMORY);
  208. }
  209. return pNode;
  210. }
  211. void lhcpDestroyHandle(PLHCSTRUCT pNode)
  212. {
  213. EnterCriticalSection(
  214. &g_csTableControl);
  215. // Remove this node from the list of handles.
  216. *(pNode->m_ppThis) = pNode->m_pNext;
  217. if (pNode->m_pNext!=NULL)
  218. {
  219. pNode->m_pNext->m_ppThis = pNode->m_ppThis;
  220. }
  221. lhcpFreeObjectHandle(
  222. pNode); // Invalidates the structure and frees the memory
  223. LeaveCriticalSection(
  224. &g_csTableControl);
  225. }
  226. BOOL lhcInitialize()
  227. {
  228. PWSTR pszPath = NULL;
  229. PWSTR pszFileName;
  230. HANDLE hFind = INVALID_HANDLE_VALUE;
  231. WIN32_FIND_DATA FindData;
  232. BOOL bResult;
  233. PLIBRARY_DESCRIPTOR pLibrary = NULL;
  234. PLIBRARY_NODE pNode = NULL;
  235. WCHAR pszLibraryName[64];
  236. InitializeCriticalSection(
  237. &g_csTableControl);
  238. pszPath = lhcpGetExeDirectory();
  239. if (NULL==pszPath)
  240. {
  241. goto Error;
  242. }
  243. pszFileName = pszPath + wcslen(pszPath);
  244. wcscat(
  245. pszFileName,
  246. L"*.lhc");
  247. hFind = FindFirstFileW(
  248. pszPath,
  249. &FindData);
  250. bResult = (hFind!=INVALID_HANDLE_VALUE);
  251. if (!bResult)
  252. {
  253. goto Error;
  254. }
  255. while (bResult)
  256. {
  257. wcscpy(
  258. pszFileName,
  259. FindData.cFileName);
  260. pLibrary = lhclLoadLibrary(
  261. pszPath);
  262. if (pLibrary==NULL)
  263. {
  264. wprintf(
  265. L"Unable to load (%u).\n",
  266. pszFileName,
  267. GetLastError());
  268. }
  269. else
  270. {
  271. lhclGetLibraryName(
  272. pLibrary,
  273. pszLibraryName,
  274. 64);
  275. wprintf(
  276. L"Loaded %s library.\n",
  277. pszLibraryName);
  278. pNode = lhcpNewLibraryNode();
  279. if (NULL==pNode)
  280. {
  281. SetLastError(
  282. ERROR_NOT_ENOUGH_MEMORY);
  283. goto Error;
  284. // Out of memory is fatal
  285. }
  286. pNode->m_pLibrary = pLibrary;
  287. pNode->m_pNext = g_pLibraryList;
  288. g_pLibraryList = pNode;
  289. pNode = NULL;
  290. pLibrary = NULL;
  291. }
  292. bResult = FindNextFileW(
  293. hFind,
  294. &FindData);
  295. }
  296. FindClose(hFind);
  297. free(pszPath);
  298. return g_pLibraryList!=NULL;
  299. Error:
  300. if (pLibrary!=NULL)
  301. {
  302. lhclFreeLibrary(pLibrary);
  303. }
  304. if (pszPath!=NULL)
  305. {
  306. free(pszPath);
  307. }
  308. if (pNode!=NULL)
  309. {
  310. free(pszPath);
  311. }
  312. if (hFind!=INVALID_HANDLE_VALUE)
  313. {
  314. FindClose(hFind);
  315. }
  316. // We need to unload the libraries that successfully loaded.
  317. lhcFinalize();
  318. return FALSE;
  319. }
  320. void lhcFinalize()
  321. {
  322. PLIBRARY_NODE pNode;
  323. WCHAR pszLibraryName[64];
  324. while (g_pObjectList!=NULL)
  325. {
  326. lhcClose(
  327. g_pObjectList);
  328. }
  329. while (g_pLibraryList!=NULL)
  330. {
  331. pNode = g_pLibraryList;
  332. g_pLibraryList = g_pLibraryList->m_pNext;
  333. lhclGetLibraryName(
  334. pNode->m_pLibrary,
  335. pszLibraryName,
  336. 64);
  337. lhclFreeLibrary(
  338. pNode->m_pLibrary);
  339. wprintf(
  340. L"Unloaded %s library.\n",
  341. pszLibraryName);
  342. lhcpFreeLibraryNode(
  343. pNode);
  344. }
  345. }
  346. LHCHANDLE lhcOpen(PCWSTR pcszPortSpec)
  347. {
  348. PLIBRARY_NODE pLibraryNode = g_pLibraryList;
  349. PLHCOBJECT_DESCRIPTOR pObject = NULL;
  350. PLHCSTRUCT hObject;
  351. while (pLibraryNode!=NULL && pObject==NULL)
  352. {
  353. // Try libraries one at a time until one opens successfully
  354. pObject = lhclOpen(
  355. pLibraryNode->m_pLibrary,
  356. pcszPortSpec);
  357. if (!pObject)
  358. {
  359. pLibraryNode = pLibraryNode->m_pNext;
  360. }
  361. }
  362. if (!pObject)
  363. {
  364. goto Error;
  365. }
  366. hObject = lhcpCreateHandle(
  367. pLibraryNode->m_pLibrary,
  368. pObject);
  369. if (hObject==NULL)
  370. {
  371. SetLastError(
  372. ERROR_NOT_ENOUGH_MEMORY);
  373. goto Error;
  374. }
  375. return hObject;
  376. Error:
  377. if (pObject!=NULL)
  378. {
  379. lhclClose(
  380. pLibraryNode->m_pLibrary,
  381. pObject);
  382. }
  383. return NULL;
  384. }
  385. BOOL lhcRead(
  386. LHCHANDLE hObject,
  387. PVOID pBuffer,
  388. DWORD dwBufferSize,
  389. PDWORD pdwBytesRead)
  390. {
  391. PLIBRARY_DESCRIPTOR pLibrary;
  392. PLHCOBJECT_DESCRIPTOR pObject;
  393. if (!lhcpIsValidHandle(hObject))
  394. {
  395. goto Error;
  396. }
  397. EnterCriticalSection(
  398. &g_csTableControl);
  399. // Ensure consistent information
  400. pLibrary = ((PLHCSTRUCT)hObject)->m_pLibrary;
  401. pObject = ((PLHCSTRUCT)hObject)->m_pObject;
  402. LeaveCriticalSection(
  403. &g_csTableControl);
  404. return lhclRead(
  405. pLibrary,
  406. pObject,
  407. pBuffer,
  408. dwBufferSize,
  409. pdwBytesRead);
  410. Error:
  411. return FALSE;
  412. }
  413. BOOL lhcWrite(
  414. LHCHANDLE hObject,
  415. PVOID pBuffer,
  416. DWORD dwBufferSize)
  417. {
  418. PLIBRARY_DESCRIPTOR pLibrary;
  419. PLHCOBJECT_DESCRIPTOR pObject;
  420. if (!lhcpIsValidHandle(hObject))
  421. {
  422. goto Error;
  423. }
  424. // Ensure consistent information by using the critical section
  425. EnterCriticalSection(
  426. &g_csTableControl);
  427. // Ensure consistent information
  428. pLibrary = ((PLHCSTRUCT)hObject)->m_pLibrary;
  429. pObject = ((PLHCSTRUCT)hObject)->m_pObject;
  430. LeaveCriticalSection(
  431. &g_csTableControl);
  432. return lhclWrite(
  433. pLibrary,
  434. pObject,
  435. pBuffer,
  436. dwBufferSize);
  437. Error:
  438. return FALSE;
  439. }
  440. BOOL lhcClose(
  441. LHCHANDLE hObject)
  442. {
  443. PLIBRARY_DESCRIPTOR pLibrary;
  444. PLHCOBJECT_DESCRIPTOR pObject;
  445. if (!lhcpIsValidHandle(hObject))
  446. {
  447. goto Error;
  448. }
  449. // Ensure consistent information by using the critical section
  450. EnterCriticalSection(
  451. &g_csTableControl);
  452. // Ensure consistent information
  453. pLibrary = ((PLHCSTRUCT)hObject)->m_pLibrary;
  454. pObject = ((PLHCSTRUCT)hObject)->m_pObject;
  455. lhcpDestroyHandle(
  456. hObject);
  457. LeaveCriticalSection(
  458. &g_csTableControl);
  459. return lhclClose(
  460. pLibrary,
  461. pObject);
  462. Error:
  463. return FALSE;
  464. }