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.

516 lines
16 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. DIC.c
  5. ++*/
  6. #include <windows.h>
  7. #include <winerror.h>
  8. #include <immdev.h>
  9. #include "imeattr.h"
  10. #include "imedefs.h"
  11. #include "imerc.h"
  12. #if !defined(ROMANIME)
  13. #if !defined(WINIME) && !defined(UNICDIME)
  14. /**********************************************************************/
  15. /* MemoryLess() */
  16. /**********************************************************************/
  17. void PASCAL MemoryLess(
  18. #if defined(UNIIME)
  19. LPINSTDATAL lpInstL,
  20. LPIMEL lpImeL,
  21. #endif
  22. DWORD fdwErrMsg)
  23. {
  24. TCHAR szErrMsg[64];
  25. if (lpImeL->fdwErrMsg & fdwErrMsg) {
  26. // message already prompted
  27. return;
  28. }
  29. LoadString(hInst, IDS_MEM_LESS_ERR, szErrMsg, sizeof(szErrMsg)/sizeof(TCHAR));
  30. lpImeL->fdwErrMsg |= fdwErrMsg;
  31. MessageBeep((UINT)-1);
  32. MessageBox((HWND)NULL, szErrMsg, lpImeL->szIMEName,
  33. MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
  34. return;
  35. }
  36. /**********************************************************************/
  37. /* ReadUsrDicToMem() */
  38. /* Return Value: */
  39. /* TRUE - successful, FALSE - failure */
  40. /**********************************************************************/
  41. BOOL PASCAL ReadUsrDicToMem(
  42. #if defined(UNIIME)
  43. LPINSTDATAL lpInstL,
  44. LPIMEL lpImeL,
  45. #endif
  46. HANDLE hUsrDicFile,
  47. DWORD dwUsrDicSize,
  48. UINT uUsrDicSize,
  49. UINT uRecLen,
  50. UINT uReadLen,
  51. UINT uWriteLen)
  52. {
  53. LPBYTE lpUsrDicMem, lpMem, lpMemLimit;
  54. DWORD dwPos, dwReadByte;
  55. if (dwUsrDicSize < 258) { // no char in this dictionary
  56. return (TRUE);
  57. }
  58. lpUsrDicMem = MapViewOfFile(lpInstL->hUsrDicMem, FILE_MAP_WRITE, 0, 0,
  59. uUsrDicSize + 20);
  60. if (!lpUsrDicMem) {
  61. CloseHandle(lpInstL->hUsrDicMem);
  62. MemoryLess(
  63. #if defined(UNIIME)
  64. lpInstL, lpImeL,
  65. #endif
  66. ERRMSG_MEM_USRDIC);
  67. lpInstL->hUsrDicMem = NULL;
  68. return (FALSE);
  69. }
  70. lpMemLimit = lpUsrDicMem + uUsrDicSize;
  71. // read in data, skip header - two headers are similiar
  72. dwPos = SetFilePointer(hUsrDicFile, 258, (LPLONG)NULL, FILE_BEGIN);
  73. for (lpMem = lpUsrDicMem; dwPos < dwUsrDicSize; lpMem += uWriteLen) {
  74. short i;
  75. DWORD dwPattern;
  76. BOOL retVal;
  77. if (lpMem >= lpMemLimit) {
  78. break;
  79. }
  80. retVal = ReadFile(hUsrDicFile, lpMem, uReadLen, &dwReadByte,
  81. (LPOVERLAPPED)NULL);
  82. if ( retVal == FALSE )
  83. {
  84. UnmapViewOfFile(lpUsrDicMem);
  85. CloseHandle(lpInstL->hUsrDicMem);
  86. MemoryLess(
  87. #if defined(UNIIME)
  88. lpInstL, lpImeL,
  89. #endif
  90. ERRMSG_MEM_USRDIC);
  91. lpInstL->hUsrDicMem = NULL;
  92. return (FALSE);
  93. }
  94. // Compress the sequence code and put the first char most significant.
  95. // Limitation - 32 bits only
  96. dwPattern = 0;
  97. for (i = 0; i < lpImeL->nMaxKey; i++) {
  98. dwPattern <<= lpImeL->nSeqBits;
  99. dwPattern |= *(lpMem + 2 + i);
  100. }
  101. *(LPUNADWORD)(lpMem + 2) = dwPattern;
  102. // go to next record
  103. dwPos = SetFilePointer(hUsrDicFile, dwPos + uRecLen, (LPLONG)NULL,
  104. FILE_BEGIN);
  105. }
  106. UnmapViewOfFile(lpUsrDicMem);
  107. return (TRUE);
  108. }
  109. /**********************************************************************/
  110. /* LoadUsrDicFile() */
  111. /* Description: */
  112. /* try to convert to sequence code format, compression and */
  113. /* don't use two way to search */
  114. /**********************************************************************/
  115. void PASCAL LoadUsrDicFile( // load user dic file into memory
  116. LPINSTDATAL lpInstL,
  117. LPIMEL lpImeL)
  118. {
  119. HANDLE hReadUsrDicMem;
  120. HANDLE hUsrDicFile;
  121. DWORD dwUsrDicFileSize;
  122. UINT uRecLen, uReadLen, uWriteLen;
  123. UINT uUsrDicSize;
  124. BOOL fRet;
  125. // no user dictionary
  126. if (!lpImeL->szUsrDicMap[0]) {
  127. lpImeL->uUsrDicSize = 0;
  128. CloseHandle(lpInstL->hUsrDicMem);
  129. lpInstL->hUsrDicMem = NULL;
  130. lpImeL->fdwErrMsg &= ~(ERRMSG_LOAD_USRDIC | ERRMSG_MEM_USRDIC);
  131. return;
  132. }
  133. if (lpInstL->hUsrDicMem) {
  134. // the memory is already here
  135. goto LoadUsrDicErrMsg;
  136. }
  137. hReadUsrDicMem = OpenFileMapping(FILE_MAP_READ, FALSE,
  138. lpImeL->szUsrDicMap);
  139. if (hReadUsrDicMem) {
  140. // another process already create a mapping file, we will use it
  141. goto LoadUsrDicMem;
  142. }
  143. // read the user dic file into memory
  144. hUsrDicFile = CreateFile(lpImeL->szUsrDic, GENERIC_READ,
  145. FILE_SHARE_READ|FILE_SHARE_WRITE,
  146. NULL, OPEN_EXISTING,
  147. FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
  148. if (hUsrDicFile != INVALID_HANDLE_VALUE) { // OK
  149. goto OpenUsrDicFile;
  150. }
  151. // if the work station version, SHARE_WRITE may fail
  152. hUsrDicFile = CreateFile(lpImeL->szUsrDic, GENERIC_READ,
  153. FILE_SHARE_READ,
  154. NULL, OPEN_EXISTING,
  155. FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
  156. OpenUsrDicFile:
  157. if (hUsrDicFile != INVALID_HANDLE_VALUE) { // OK
  158. lpImeL->fdwErrMsg &= ~(ERRMSG_LOAD_USRDIC);
  159. } else if (lpImeL->fdwErrMsg & ERRMSG_LOAD_USRDIC) {
  160. // already prompt error message before, no more
  161. return;
  162. } else {
  163. TCHAR szFmtStr[64];
  164. TCHAR szErrMsg[2 * MAX_PATH];
  165. HRESULT hr;
  166. // temp use szIMEName as format string buffer of error message
  167. LoadString(hInst, IDS_FILE_OPEN_ERR, szFmtStr, sizeof(szFmtStr)/sizeof(TCHAR));
  168. hr = StringCchPrintf(szErrMsg, ARRAYSIZE(szErrMsg), szFmtStr, lpImeL->szUsrDic);
  169. if (FAILED(hr))
  170. return;
  171. lpImeL->fdwErrMsg |= ERRMSG_LOAD_USRDIC;
  172. MessageBeep((UINT)-1);
  173. MessageBox((HWND)NULL, szErrMsg, lpImeL->szIMEName,
  174. MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
  175. return;
  176. }
  177. // one record length - only sequence code, now
  178. uRecLen = lpImeL->nMaxKey + 4;
  179. // read sequence code and internal code
  180. uReadLen = lpImeL->nMaxKey + 2;
  181. // length write into memory handle
  182. uWriteLen = lpImeL->nSeqBytes + 2;
  183. // get the length of the file
  184. dwUsrDicFileSize = GetFileSize(hUsrDicFile, (LPDWORD)NULL);
  185. uUsrDicSize = (UINT)(dwUsrDicFileSize - 256) / uRecLen * uWriteLen;
  186. // max EUDC chars
  187. lpInstL->hUsrDicMem = CreateFileMapping(INVALID_HANDLE_VALUE,
  188. NULL, PAGE_READWRITE, 0, MAX_EUDC_CHARS * uWriteLen + 20,
  189. lpImeL->szUsrDicMap);
  190. if (!lpInstL->hUsrDicMem) {
  191. MemoryLess(
  192. #if defined(UNIIME)
  193. lpInstL, lpImeL,
  194. #endif
  195. ERRMSG_MEM_USRDIC);
  196. fRet = FALSE;
  197. } else if (GetLastError() == ERROR_ALREADY_EXISTS) {
  198. // another process also create another one, we will use it
  199. hReadUsrDicMem = OpenFileMapping(FILE_MAP_READ, FALSE,
  200. lpImeL->szUsrDicMap);
  201. CloseHandle(lpInstL->hUsrDicMem);
  202. CloseHandle(hUsrDicFile);
  203. if (hReadUsrDicMem != NULL) { // OK
  204. lpInstL->hUsrDicMem = hReadUsrDicMem;
  205. lpImeL->uUsrDicSize = uUsrDicSize;
  206. lpImeL->fdwErrMsg &= ~(ERRMSG_MEM_USRDIC);
  207. } else {
  208. MemoryLess(
  209. #if defined(UNIIME)
  210. lpInstL, lpImeL,
  211. #endif
  212. ERRMSG_MEM_USRDIC);
  213. lpInstL->hUsrDicMem = NULL;
  214. }
  215. return;
  216. } else {
  217. fRet = ReadUsrDicToMem(
  218. #if defined(UNIIME)
  219. lpInstL, lpImeL,
  220. #endif
  221. hUsrDicFile, dwUsrDicFileSize, uUsrDicSize, uRecLen,
  222. uReadLen, uWriteLen);
  223. }
  224. CloseHandle(hUsrDicFile);
  225. if (!fRet) {
  226. if (lpInstL->hUsrDicMem) {
  227. CloseHandle(lpInstL->hUsrDicMem);
  228. lpInstL->hUsrDicMem = NULL;
  229. }
  230. return;
  231. }
  232. // open a read only memory for EUDC table
  233. hReadUsrDicMem = OpenFileMapping(FILE_MAP_READ, FALSE,
  234. lpImeL->szUsrDicMap);
  235. // reopen a read file and close the original write file
  236. CloseHandle(lpInstL->hUsrDicMem);
  237. lpImeL->uUsrDicSize = uUsrDicSize;
  238. LoadUsrDicMem:
  239. lpInstL->hUsrDicMem = hReadUsrDicMem;
  240. LoadUsrDicErrMsg:
  241. lpImeL->fdwErrMsg &= ~(ERRMSG_LOAD_USRDIC | ERRMSG_MEM_USRDIC);
  242. return;
  243. }
  244. /**********************************************************************/
  245. /* LoadOneTable() */
  246. /* Description: */
  247. /* memory handle & size of .TBL file will be assigned to */
  248. /* lpImeL */
  249. /* Eeturn Value: */
  250. /* length of directory of the .TBL file */
  251. /**********************************************************************/
  252. UINT PASCAL LoadOneTable( // load one of table file
  253. #if defined(UNIIME)
  254. LPINSTDATAL lpInstL,
  255. LPIMEL lpImeL,
  256. #endif
  257. LPTSTR szTable, // file name of .TBL
  258. UINT uIndex, // the index of array to store memory handle
  259. UINT uLen, // length of the directory
  260. LPTSTR szPath) // buffer for directory
  261. {
  262. HANDLE hTblFile;
  263. HGLOBAL hMap;
  264. DWORD dwFileSize;
  265. PSECURITY_ATTRIBUTES psa;
  266. if (lpInstL->hMapTbl[uIndex]) { // already loaded
  267. CloseHandle(lpInstL->hMapTbl[uIndex]);
  268. lpInstL->hMapTbl[uIndex] = (HANDLE)NULL;
  269. }
  270. psa = CreateSecurityAttributes();
  271. if (uLen) {
  272. lstrcpy((LPTSTR)&szPath[uLen], szTable);
  273. hTblFile = CreateFile(szPath, GENERIC_READ,
  274. FILE_SHARE_READ|FILE_SHARE_WRITE,
  275. psa, OPEN_EXISTING,
  276. FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
  277. if (hTblFile != INVALID_HANDLE_VALUE) {
  278. goto OpenDicFile;
  279. }
  280. // if the work station version, SHARE_WRITE will fail
  281. hTblFile = CreateFile(szPath, GENERIC_READ,
  282. FILE_SHARE_READ, psa,
  283. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
  284. } else {
  285. // try system directory next
  286. uLen = GetSystemDirectory(szPath, MAX_PATH);
  287. if (szPath[uLen - 1] != '\\') { // consider N:\ ;
  288. szPath[uLen++] = '\\';
  289. }
  290. lstrcpy((LPTSTR)&szPath[uLen], szTable);
  291. hTblFile = CreateFile(szPath, GENERIC_READ,
  292. FILE_SHARE_READ|FILE_SHARE_WRITE,
  293. psa, OPEN_EXISTING,
  294. FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
  295. if (hTblFile != INVALID_HANDLE_VALUE) {
  296. goto OpenDicFile;
  297. }
  298. // if the work station version, SHARE_WRITE will fail
  299. hTblFile = CreateFile(szPath, GENERIC_READ,
  300. FILE_SHARE_READ, psa,
  301. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
  302. }
  303. OpenDicFile:
  304. // can not find the table file
  305. if (hTblFile != INVALID_HANDLE_VALUE) { // OK
  306. } else if (lpImeL->fdwErrMsg & (ERRMSG_LOAD_0 << uIndex)) {
  307. // already prompt error message before, no more
  308. FreeSecurityAttributes(psa);
  309. return (0);
  310. } else { // prompt error message
  311. TCHAR szFmtStr[64];
  312. TCHAR szErrMsg[2 * MAX_PATH];
  313. HRESULT hr;
  314. #if defined(WINAR30)
  315. if(uIndex==4 || uIndex==5)
  316. {
  317. return (uLen);
  318. }
  319. #endif
  320. // temp use szIMEName as format string buffer of error message
  321. LoadString(hInst, IDS_FILE_OPEN_ERR, szFmtStr, sizeof(szFmtStr)/sizeof(TCHAR));
  322. hr = StringCchPrintf(szErrMsg, ARRAYSIZE(szErrMsg), szFmtStr, szTable);
  323. if (FAILED(hr))
  324. return 0;
  325. lpImeL->fdwErrMsg |= ERRMSG_LOAD_0 << uIndex;
  326. MessageBeep((UINT)-1);
  327. MessageBox((HWND)NULL, szErrMsg, lpImeL->szIMEName,
  328. MB_OK|MB_ICONHAND|MB_TASKMODAL|MB_TOPMOST);
  329. FreeSecurityAttributes(psa);
  330. return (0);
  331. }
  332. lpImeL->fdwErrMsg &= ~(ERRMSG_LOAD_0 << uIndex);
  333. // create file mapping for IME tables
  334. hMap = CreateFileMapping((HANDLE)hTblFile, psa, PAGE_READONLY,
  335. 0, 0, szTable);
  336. dwFileSize = GetFileSize(hTblFile, (LPDWORD)NULL);
  337. CloseHandle(hTblFile);
  338. FreeSecurityAttributes(psa);
  339. if (!hMap) {
  340. MemoryLess(
  341. #if defined(UNIIME)
  342. lpInstL, lpImeL,
  343. #endif
  344. ERRMSG_MEM_0 << uIndex);
  345. return (0);
  346. }
  347. lpImeL->fdwErrMsg &= ~(ERRMSG_MEM_0 << uIndex);
  348. lpInstL->hMapTbl[uIndex] = hMap;
  349. // get file length
  350. lpImeL->uTblSize[uIndex] = dwFileSize;
  351. return (uLen);
  352. }
  353. #endif
  354. /**********************************************************************/
  355. /* LoadTable() */
  356. /* Return Value: */
  357. /* TRUE - successful, FALSE - failure */
  358. /**********************************************************************/
  359. BOOL PASCAL LoadTable( // check the table files of IME, include user
  360. // defined dictionary
  361. LPINSTDATAL lpInstL,
  362. LPIMEL lpImeL)
  363. {
  364. #if !defined(WINIME) && !defined(UNICDIME)
  365. int i;
  366. UINT uLen;
  367. TCHAR szBuf[MAX_PATH];
  368. #endif
  369. if (lpInstL->fdwTblLoad == TBL_LOADED) {
  370. return (TRUE);
  371. }
  372. #if !defined(WINIME) && !defined(UNICDIME)
  373. uLen = 0;
  374. // A15.TBL, A234.TBL, ACODE.TBL, / PHON.TBL, PHONPTR.TBL, PHONCODE.TBL,
  375. for (i = 0; i < MAX_IME_TABLES; i++) {
  376. if (!*lpImeL->szTblFile[i]) {
  377. } else if (uLen = LoadOneTable(
  378. #if defined(UNIIME)
  379. lpInstL, lpImeL,
  380. #endif
  381. lpImeL->szTblFile[i], i, uLen, szBuf)) {
  382. } else {
  383. int j;
  384. for (j = 0; j < i; j++) {
  385. if (lpInstL->hMapTbl[j]) {
  386. CloseHandle(lpInstL->hMapTbl[j]);
  387. lpInstL->hMapTbl[j] = (HANDLE)NULL;
  388. }
  389. }
  390. lpInstL->fdwTblLoad = TBL_LOADERR;
  391. return (FALSE);
  392. }
  393. }
  394. #endif
  395. lpInstL->fdwTblLoad = TBL_LOADED;
  396. #if !defined(WINIME) && !defined(UNICDIME)
  397. if (lpImeL->szUsrDic[0]) {
  398. LoadUsrDicFile(lpInstL, lpImeL);
  399. }
  400. #endif
  401. return (TRUE);
  402. }
  403. /**********************************************************************/
  404. /* FreeTable() */
  405. /**********************************************************************/
  406. void PASCAL FreeTable(
  407. LPINSTDATAL lpInstL)
  408. {
  409. #if !defined(WINIME) && !defined(UNICDIME)
  410. int i;
  411. // A15.TBL, A234.TBL, ACODE.TBL, / PHON.TBL, PHONPTR.TBL, PHONCODE.TBL,
  412. for (i = 0; i < MAX_IME_TABLES; i++) {
  413. if (lpInstL->hMapTbl[i]) {
  414. CloseHandle(lpInstL->hMapTbl[i]);
  415. lpInstL->hMapTbl[i] = (HANDLE)NULL;
  416. }
  417. }
  418. // do not need to free phrase data base, maybe next IME will use it
  419. // uniime.dll will free it on library detach time
  420. if (lpInstL->hUsrDicMem) {
  421. CloseHandle(lpInstL->hUsrDicMem);
  422. lpInstL->hUsrDicMem = (HANDLE)NULL;
  423. }
  424. #endif
  425. lpInstL->fdwTblLoad = TBL_NOTLOADED;
  426. return;
  427. }
  428. #endif // !defined(ROMANIME)