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.

456 lines
8.4 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. main.c
  5. Abstract:
  6. Main source file of migutil.dll
  7. Author:
  8. Jim Schmidt (jimschm) 01-Aug-1996
  9. Revision History:
  10. marcw 2-Sep-1999 Moved over from Win9xUpg project.
  11. jimschm 23-Sep-1998 Start thread
  12. marcw 23-Sep-1998 Locale fix
  13. jimschm 03-Nov-1997 Added TextAlloc routines
  14. marcw 22-Jul-1997 Added IS<platform> functions.
  15. --*/
  16. #include "pch.h"
  17. #include "utilsp.h"
  18. #include "locale.h"
  19. //#define DEBUG_ALL_FILES
  20. HINSTANCE g_hInst;
  21. HANDLE g_hHeap;
  22. OSVERSIONINFOA g_OsInfo;
  23. OUR_CRITICAL_SECTION g_MemDbCs;
  24. #define TEXT_GROWTH_SIZE 65536
  25. //
  26. // OS-dependent flags for MultiByteToWideChar
  27. //
  28. DWORD g_MigutilWCToMBFlags = 0;
  29. //
  30. // g_ShortTermAllocTable is the default table used for resource string
  31. // management. New strings are allocated from the table.
  32. //
  33. // Allocation tables are very simple ways to store strings loaded in from
  34. // the exe image. The loaded string is copied into the table and kept
  35. // around until it is explicitly freed. Multiple attempts at getting the
  36. // same resource string return the same string, inc'ing a use counter.
  37. //
  38. // g_OutOfMemoryTable is the table used to hold out-of-memory text. It
  39. // is loaded up at init time and is kept in memory for the whole time
  40. // migutil is in use, so out-of-memory messages can always be displayed.
  41. //
  42. PGROWBUFFER g_ShortTermAllocTable;
  43. PGROWBUFFER g_OutOfMemoryTable;
  44. //
  45. // We make sure the message APIs (GetStringResource, ParseMessageID, etc)
  46. // are thread-safe
  47. //
  48. OUR_CRITICAL_SECTION g_MessageCs;
  49. //
  50. // The PoolMem routines must also be thread-safe
  51. //
  52. OUR_CRITICAL_SECTION g_PmCs;
  53. //
  54. // MemAlloc critical section
  55. //
  56. OUR_CRITICAL_SECTION g_MemAllocCs;
  57. //
  58. // The following pools are used for text management. g_RegistryApiPool is
  59. // for reg.c, g_PathsPool is for the JoinPaths/DuplicatePath/etc routines,
  60. // and g_TextPool is for AllocText, DupText, etc.
  61. //
  62. PMHANDLE g_RegistryApiPool;
  63. PMHANDLE g_PathsPool;
  64. PMHANDLE g_TextPool;
  65. VOID
  66. UtInitialize (
  67. IN HANDLE Heap OPTIONAL
  68. )
  69. {
  70. //
  71. // Set globals
  72. //
  73. if (Heap) {
  74. g_hHeap = Heap;
  75. } else {
  76. g_hHeap = GetProcessHeap();
  77. }
  78. g_hInst = GetModuleHandle (NULL);
  79. //
  80. // Load in OSVERSION info.
  81. //
  82. g_OsInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  83. GetVersionExA (&g_OsInfo);
  84. //
  85. // Initialize log
  86. //
  87. Init_Log (NULL);
  88. //
  89. // Create critical sections
  90. //
  91. InitializeOurCriticalSection (&g_MemAllocCs);
  92. InitializeOurCriticalSection (&g_MemDbCs);
  93. InitializeOurCriticalSection (&g_PmCs);
  94. InitializeOurCriticalSection (&g_MessageCs);
  95. //
  96. // Now that MemAlloc will work, initialize allocation tracking
  97. //
  98. InitAllocationTracking();
  99. //
  100. // Create the short-term alloc table for string resource utils
  101. //
  102. g_ShortTermAllocTable = CreateAllocTable();
  103. //
  104. // MultiByteToWideChar has desirable flags that only function on NT
  105. //
  106. g_MigutilWCToMBFlags = (ISNT()) ? WC_NO_BEST_FIT_CHARS : 0;
  107. #ifdef _lint
  108. g_MigutilWCToMBFlags = g_MigutilWCToMBFlags;
  109. #endif
  110. //
  111. // Create pools used by utils.lib code
  112. //
  113. g_RegistryApiPool = PmCreateNamedPool ("Registry API");
  114. g_PathsPool = PmCreateNamedPool ("Paths");
  115. g_TextPool = PmCreateNamedPool ("Text");
  116. PmSetMinimumGrowthSize (g_TextPool, TEXT_GROWTH_SIZE);
  117. ObsInitialize ();
  118. ElInitialize ();
  119. //
  120. // The "out of memory" message
  121. //
  122. g_OutOfMemoryTable = CreateAllocTable();
  123. g_OutOfMemoryRetry = GetStringResourceExA (
  124. g_OutOfMemoryTable,
  125. 10001 /* MSG_OUT_OF_MEMORY_RETRY */
  126. );
  127. g_OutOfMemoryString = GetStringResourceExA (
  128. g_OutOfMemoryTable,
  129. 10002 /* MSG_OUT_OF_MEMORY */
  130. );
  131. if (!g_OutOfMemoryString || !g_OutOfMemoryRetry) {
  132. DEBUGMSG ((
  133. DBG_WARNING,
  134. "Cannot load out of memory messages; resources 10001 and 10002 do not exist"
  135. ));
  136. }
  137. //
  138. // set the locale to the system locale. Not doing this can cause isspace
  139. // to AV in certain MBSCHR circumstances.
  140. //
  141. setlocale(LC_ALL,"");
  142. }
  143. VOID
  144. UtTerminate (
  145. VOID
  146. )
  147. {
  148. //
  149. // Free utility pools
  150. //
  151. ElTerminate ();
  152. ObsTerminate ();
  153. if (g_RegistryApiPool) {
  154. PmDestroyPool (g_RegistryApiPool);
  155. }
  156. if (g_PathsPool) {
  157. PmDestroyPool (g_PathsPool);
  158. }
  159. if (g_TextPool) {
  160. PmDestroyPool (g_TextPool);
  161. }
  162. if (g_ShortTermAllocTable) {
  163. DestroyAllocTable (g_ShortTermAllocTable);
  164. }
  165. if (g_OutOfMemoryTable) {
  166. DestroyAllocTable (g_OutOfMemoryTable);
  167. }
  168. FreeAllocationTracking();
  169. //
  170. // Clean up handles used by critical sections
  171. //
  172. DeleteOurCriticalSection (&g_MemAllocCs);
  173. DeleteOurCriticalSection (&g_MemDbCs);
  174. DeleteOurCriticalSection (&g_PmCs);
  175. DeleteOurCriticalSection (&g_MessageCs);
  176. //
  177. // MUST BE VERY LAST CODE TO RUN
  178. //
  179. DumpHeapStats();
  180. Exit_Log ();
  181. }
  182. #define WIDTH(rect) (rect.right - rect.left)
  183. #define HEIGHT(rect) (rect.bottom - rect.top)
  184. void
  185. CenterWindow (
  186. IN HWND hwnd,
  187. IN HWND Parent
  188. )
  189. {
  190. RECT WndRect, ParentRect;
  191. int x, y;
  192. if (!Parent) {
  193. ParentRect.left = 0;
  194. ParentRect.top = 0;
  195. ParentRect.right = GetSystemMetrics (SM_CXFULLSCREEN);
  196. ParentRect.bottom = GetSystemMetrics (SM_CYFULLSCREEN);
  197. } else {
  198. GetWindowRect (Parent, &ParentRect);
  199. }
  200. MYASSERT (IsWindow (hwnd));
  201. GetWindowRect (hwnd, &WndRect);
  202. x = ParentRect.left + (WIDTH(ParentRect) - WIDTH(WndRect)) / 2;
  203. y = ParentRect.top + (HEIGHT(ParentRect) - HEIGHT(WndRect)) / 2;
  204. SetWindowPos (hwnd, NULL, x, y, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
  205. }
  206. static INT g_MigUtilWaitCounter = 0;
  207. static HCURSOR g_MigUtilWaitCursor = NULL;
  208. VOID
  209. TurnOnWaitCursor (
  210. VOID
  211. )
  212. /*++
  213. Routine Description:
  214. TurnOnWaitCursor sets the cursor to IDC_WAIT. It maintains a use
  215. counter, so code requring the wait cursor can be nested.
  216. Arguments:
  217. none
  218. Return Value:
  219. none
  220. --*/
  221. {
  222. if (g_MigUtilWaitCounter == 0) {
  223. g_MigUtilWaitCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  224. }
  225. g_MigUtilWaitCounter++;
  226. }
  227. VOID
  228. TurnOffWaitCursor (
  229. VOID
  230. )
  231. /*++
  232. Routine Description:
  233. TurnOffWaitCursor decrements the wait cursor counter, and if it
  234. reaches zero the cursor is restored.
  235. Arguments:
  236. none
  237. Return Value:
  238. none
  239. --*/
  240. {
  241. if (!g_MigUtilWaitCounter) {
  242. DEBUGMSG ((DBG_WHOOPS, "TurnOffWaitCursor called too many times"));
  243. } else {
  244. g_MigUtilWaitCounter--;
  245. if (!g_MigUtilWaitCounter) {
  246. SetCursor (g_MigUtilWaitCursor);
  247. }
  248. }
  249. }
  250. /*++
  251. Routine Description:
  252. Win9x does not support TryEnterOurCriticalSection, so we must implement
  253. our own version because it is quite a useful function.
  254. Arguments:
  255. pcs - A pointer to an OUR_CRITICAL_SECTION object
  256. Return Value:
  257. TRUE if the function succeeded, or FALSE if it failed. See Win32
  258. SDK docs on critical sections, as these routines are identical to
  259. the caller.
  260. --*/
  261. BOOL
  262. InitializeOurCriticalSection (
  263. OUR_CRITICAL_SECTION *pcs
  264. )
  265. {
  266. // Create initially signaled, auto-reset event
  267. pcs->EventHandle = CreateEvent (NULL, FALSE, TRUE, NULL);
  268. if (!pcs->EventHandle) {
  269. return FALSE;
  270. }
  271. return TRUE;
  272. }
  273. VOID
  274. DeleteOurCriticalSection (
  275. OUR_CRITICAL_SECTION *pcs
  276. )
  277. {
  278. if (pcs->EventHandle) {
  279. CloseHandle (pcs->EventHandle);
  280. pcs->EventHandle = NULL;
  281. }
  282. }
  283. BOOL
  284. EnterOurCriticalSection (
  285. OUR_CRITICAL_SECTION *pcs
  286. )
  287. {
  288. DWORD rc;
  289. // Wait for event to become signaled, then turn it off
  290. rc = WaitForSingleObject (pcs->EventHandle, INFINITE);
  291. if (rc == WAIT_OBJECT_0) {
  292. return TRUE;
  293. }
  294. return FALSE;
  295. }
  296. VOID
  297. LeaveOurCriticalSection (
  298. OUR_CRITICAL_SECTION *pcs
  299. )
  300. {
  301. SetEvent (pcs->EventHandle);
  302. }
  303. BOOL
  304. TryEnterOurCriticalSection (
  305. OUR_CRITICAL_SECTION *pcs
  306. )
  307. {
  308. DWORD rc;
  309. rc = WaitForSingleObject (pcs->EventHandle, 0);
  310. if (rc == WAIT_OBJECT_0) {
  311. return TRUE;
  312. }
  313. return FALSE;
  314. }
  315. HANDLE
  316. StartThread (
  317. IN PTHREAD_START_ROUTINE Address,
  318. IN PVOID Arg
  319. )
  320. {
  321. DWORD DontCare;
  322. return CreateThread (NULL, 0, Address, Arg, 0, &DontCare);
  323. }