Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Kernel initialization code |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 3 | * |
| 4 | * Copyright 2000 Alexandre Julliard |
| 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2.1 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
| 17 | * License along with this library; if not, write to the Free Software |
Jonathan Ernst | 360a3f9 | 2006-05-18 14:49:52 +0200 | [diff] [blame] | 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 19 | */ |
| 20 | |
Patrik Stridvall | 33929be | 2001-07-18 21:04:23 +0000 | [diff] [blame] | 21 | #include "config.h" |
Patrik Stridvall | 9aab47e | 2002-08-28 23:42:34 +0000 | [diff] [blame] | 22 | #include "wine/port.h" |
Patrik Stridvall | 33929be | 2001-07-18 21:04:23 +0000 | [diff] [blame] | 23 | |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 24 | #include <assert.h> |
Andreas Mohr | 04a8eda | 2000-10-17 00:27:47 +0000 | [diff] [blame] | 25 | #include <ctype.h> |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 26 | #include <stdarg.h> |
James Juran | f4d5fef | 2001-01-26 20:43:40 +0000 | [diff] [blame] | 27 | #include <string.h> |
Eric Pouech | 3d4d7e0 | 2002-07-31 18:46:09 +0000 | [diff] [blame] | 28 | #include <signal.h> |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 29 | |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 30 | #include "windef.h" |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 31 | #include "winbase.h" |
Alexandre Julliard | 99d8b7f | 2002-07-31 19:19:36 +0000 | [diff] [blame] | 32 | #include "wincon.h" |
Patrik Stridvall | 9c1de6d | 2002-09-12 22:07:02 +0000 | [diff] [blame] | 33 | #include "winternl.h" |
Alexandre Julliard | 628939d | 2005-08-10 10:59:19 +0000 | [diff] [blame] | 34 | #include "wownt32.h" |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 35 | |
Alexandre Julliard | 5900867 | 2002-05-16 20:32:16 +0000 | [diff] [blame] | 36 | #include "wine/library.h" |
Alexandre Julliard | 3be5d62 | 2003-08-25 00:56:37 +0000 | [diff] [blame] | 37 | #include "kernel_private.h" |
Eric Pouech | d7d9836 | 2002-09-04 18:41:03 +0000 | [diff] [blame] | 38 | #include "console_private.h" |
Alexandre Julliard | 3baf4db | 2007-05-07 17:10:18 +0200 | [diff] [blame] | 39 | #include "wine/debug.h" |
| 40 | |
| 41 | WINE_DEFAULT_DEBUG_CHANNEL(process); |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 42 | |
Maarten Lankhorst | 768160e | 2008-12-16 16:37:46 +0100 | [diff] [blame] | 43 | extern int CDECL __wine_set_signal_handler(unsigned, int (*)(unsigned)); |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 44 | |
Alexandre Julliard | 40fb7ca | 2007-07-11 14:04:54 +0200 | [diff] [blame] | 45 | static ULONGLONG server_start_time; |
| 46 | |
Alexandre Julliard | e15aadd | 2003-05-13 00:49:49 +0000 | [diff] [blame] | 47 | /*********************************************************************** |
Alexandre Julliard | 3baf4db | 2007-05-07 17:10:18 +0200 | [diff] [blame] | 48 | * set_entry_point |
| 49 | */ |
| 50 | static void set_entry_point( HMODULE module, const char *name, DWORD rva ) |
| 51 | { |
| 52 | IMAGE_EXPORT_DIRECTORY *exports; |
| 53 | DWORD exp_size; |
| 54 | |
| 55 | if ((exports = RtlImageDirectoryEntryToData( module, TRUE, |
| 56 | IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size ))) |
| 57 | { |
| 58 | DWORD *functions = (DWORD *)((char *)module + exports->AddressOfFunctions); |
| 59 | const WORD *ordinals = (const WORD *)((const char *)module + exports->AddressOfNameOrdinals); |
| 60 | const DWORD *names = (const DWORD *)((const char *)module + exports->AddressOfNames); |
| 61 | int min = 0, max = exports->NumberOfNames - 1; |
| 62 | |
| 63 | while (min <= max) |
| 64 | { |
| 65 | int res, pos = (min + max) / 2; |
| 66 | const char *ename = (const char *)module + names[pos]; |
| 67 | if (!(res = strcmp( ename, name ))) |
| 68 | { |
| 69 | WORD ordinal = ordinals[pos]; |
| 70 | assert( ordinal < exports->NumberOfFunctions ); |
| 71 | TRACE( "setting %s at %p to %08x\n", name, &functions[ordinal], rva ); |
| 72 | functions[ordinal] = rva; |
| 73 | return; |
| 74 | } |
| 75 | if (res > 0) max = pos - 1; |
| 76 | else min = pos + 1; |
| 77 | } |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | |
| 82 | /*********************************************************************** |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 83 | * KERNEL process initialisation routine |
| 84 | */ |
Alexandre Julliard | 3baf4db | 2007-05-07 17:10:18 +0200 | [diff] [blame] | 85 | static BOOL process_attach( HMODULE module ) |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 86 | { |
Alexandre Julliard | 40fb7ca | 2007-07-11 14:04:54 +0200 | [diff] [blame] | 87 | SYSTEM_TIMEOFDAY_INFORMATION ti; |
Alexandre Julliard | 38440f5 | 2006-07-13 14:04:40 +0200 | [diff] [blame] | 88 | RTL_USER_PROCESS_PARAMETERS *params = NtCurrentTeb()->Peb->ProcessParameters; |
Alexandre Julliard | cc46132 | 2004-06-15 00:52:03 +0000 | [diff] [blame] | 89 | |
Alexandre Julliard | 40fb7ca | 2007-07-11 14:04:54 +0200 | [diff] [blame] | 90 | NtQuerySystemInformation( SystemTimeOfDayInformation, &ti, sizeof(ti), NULL ); |
| 91 | server_start_time = ti.liKeBootTime.QuadPart; |
| 92 | |
Alexandre Julliard | a3c4568 | 2003-10-14 05:32:30 +0000 | [diff] [blame] | 93 | /* Setup registry locale information */ |
| 94 | LOCALE_InitRegistry(); |
Alexandre Julliard | 6ce2570 | 2000-07-11 22:08:43 +0000 | [diff] [blame] | 95 | |
Martin Wilck | 6d886a5 | 2002-11-15 01:01:47 +0000 | [diff] [blame] | 96 | /* Setup computer name */ |
| 97 | COMPUTERNAME_Init(); |
Alexandre Julliard | 1de20ae | 2004-03-20 02:28:51 +0000 | [diff] [blame] | 98 | |
Alexandre Julliard | 38440f5 | 2006-07-13 14:04:40 +0200 | [diff] [blame] | 99 | /* convert value from server: |
| 100 | * + 0 => INVALID_HANDLE_VALUE |
| 101 | * + console handle needs to be mapped |
| 102 | */ |
| 103 | if (!params->hStdInput) |
| 104 | params->hStdInput = INVALID_HANDLE_VALUE; |
| 105 | else if (VerifyConsoleIoHandle(console_handle_map(params->hStdInput))) |
| 106 | params->hStdInput = console_handle_map(params->hStdInput); |
| 107 | |
| 108 | if (!params->hStdOutput) |
| 109 | params->hStdOutput = INVALID_HANDLE_VALUE; |
| 110 | else if (VerifyConsoleIoHandle(console_handle_map(params->hStdOutput))) |
| 111 | params->hStdOutput = console_handle_map(params->hStdOutput); |
| 112 | |
| 113 | if (!params->hStdError) |
| 114 | params->hStdError = INVALID_HANDLE_VALUE; |
| 115 | else if (VerifyConsoleIoHandle(console_handle_map(params->hStdError))) |
| 116 | params->hStdError = console_handle_map(params->hStdError); |
| 117 | |
Eric Pouech | b53b5bc | 2003-06-18 03:23:22 +0000 | [diff] [blame] | 118 | /* copy process information from ntdll */ |
| 119 | ENV_CopyStartupInformation(); |
Martin Wilck | 6d886a5 | 2002-11-15 01:01:47 +0000 | [diff] [blame] | 120 | |
Alexandre Julliard | 3baf4db | 2007-05-07 17:10:18 +0200 | [diff] [blame] | 121 | if (!(GetVersion() & 0x80000000)) |
| 122 | { |
| 123 | /* Securom checks for this one when version is NT */ |
| 124 | set_entry_point( module, "FT_Thunk", 0 ); |
| 125 | } |
Alexandre Julliard | 00ac707 | 2010-03-01 11:34:34 +0100 | [diff] [blame] | 126 | else LoadLibraryA( "krnl386.exe16" ); |
Alexandre Julliard | 389b039 | 2001-03-04 01:06:07 +0000 | [diff] [blame] | 127 | |
Eric Pouech | d7d9836 | 2002-09-04 18:41:03 +0000 | [diff] [blame] | 128 | /* finish the process initialisation for console bits, if needed */ |
Eric Pouech | 3d4d7e0 | 2002-07-31 18:46:09 +0000 | [diff] [blame] | 129 | __wine_set_signal_handler(SIGINT, CONSOLE_HandleCtrlC); |
| 130 | |
Alexandre Julliard | 38440f5 | 2006-07-13 14:04:40 +0200 | [diff] [blame] | 131 | if (params->ConsoleHandle == (HANDLE)1) /* FIXME */ |
Alexandre Julliard | 99d8b7f | 2002-07-31 19:19:36 +0000 | [diff] [blame] | 132 | { |
| 133 | HMODULE mod = GetModuleHandleA(0); |
| 134 | if (RtlImageNtHeader(mod)->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) |
| 135 | AllocConsole(); |
| 136 | } |
Alexandre Julliard | 626669e | 2006-02-05 12:24:43 +0100 | [diff] [blame] | 137 | /* else TODO for DETACHED_PROCESS: |
| 138 | * 1/ inherit console + handles |
| 139 | * 2/ create std handles, if handles are not inherited |
| 140 | * TBD when not using wineserver handles for console handles |
| 141 | */ |
Eric Pouech | b53b5bc | 2003-06-18 03:23:22 +0000 | [diff] [blame] | 142 | |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 143 | return TRUE; |
| 144 | } |
| 145 | |
| 146 | /*********************************************************************** |
| 147 | * KERNEL initialisation routine |
| 148 | */ |
Alexandre Julliard | 7196724 | 2003-10-10 00:50:56 +0000 | [diff] [blame] | 149 | BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 150 | { |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 151 | switch(reason) |
| 152 | { |
| 153 | case DLL_PROCESS_ATTACH: |
Alexandre Julliard | 475b7d2 | 2009-12-29 16:24:00 +0100 | [diff] [blame] | 154 | DisableThreadLibraryCalls( hinst ); |
Alexandre Julliard | 3baf4db | 2007-05-07 17:10:18 +0200 | [diff] [blame] | 155 | return process_attach( hinst ); |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 156 | case DLL_PROCESS_DETACH: |
Alexandre Julliard | 86c6021 | 2009-10-08 19:11:58 +0200 | [diff] [blame] | 157 | WritePrivateProfileSectionW( NULL, NULL, NULL ); |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 158 | break; |
| 159 | } |
| 160 | return TRUE; |
| 161 | } |
Alexandre Julliard | 3850c1a | 2000-08-06 02:42:46 +0000 | [diff] [blame] | 162 | |
| 163 | /*********************************************************************** |
Alexandre Julliard | c349d7d | 2004-04-28 03:53:19 +0000 | [diff] [blame] | 164 | * MulDiv (KERNEL32.@) |
| 165 | * RETURNS |
| 166 | * Result of multiplication and division |
| 167 | * -1: Overflow occurred or Divisor was 0 |
| 168 | */ |
| 169 | INT WINAPI MulDiv( INT nMultiplicand, INT nMultiplier, INT nDivisor) |
| 170 | { |
| 171 | LONGLONG ret; |
| 172 | |
| 173 | if (!nDivisor) return -1; |
| 174 | |
| 175 | /* We want to deal with a positive divisor to simplify the logic. */ |
| 176 | if (nDivisor < 0) |
| 177 | { |
| 178 | nMultiplicand = - nMultiplicand; |
| 179 | nDivisor = -nDivisor; |
| 180 | } |
| 181 | |
| 182 | /* If the result is positive, we "add" to round. else, we subtract to round. */ |
| 183 | if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) || |
| 184 | ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) ) |
| 185 | ret = (((LONGLONG)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor; |
| 186 | else |
| 187 | ret = (((LONGLONG)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor; |
| 188 | |
| 189 | if ((ret > 2147483647) || (ret < -2147483647)) return -1; |
| 190 | return ret; |
| 191 | } |
Alexandre Julliard | 9ad5628 | 2005-07-14 10:32:46 +0000 | [diff] [blame] | 192 | |
| 193 | |
Alexandre Julliard | 40fb7ca | 2007-07-11 14:04:54 +0200 | [diff] [blame] | 194 | /****************************************************************************** |
| 195 | * GetTickCount64 (KERNEL32.@) |
| 196 | */ |
| 197 | ULONGLONG WINAPI GetTickCount64(void) |
| 198 | { |
| 199 | LARGE_INTEGER now; |
| 200 | |
| 201 | NtQuerySystemTime( &now ); |
| 202 | return (now.QuadPart - server_start_time) / 10000; |
| 203 | } |
| 204 | |
| 205 | |
Alexandre Julliard | 9ad5628 | 2005-07-14 10:32:46 +0000 | [diff] [blame] | 206 | /*********************************************************************** |
Alexandre Julliard | 9ad5628 | 2005-07-14 10:32:46 +0000 | [diff] [blame] | 207 | * GetTickCount (KERNEL32.@) |
| 208 | * |
| 209 | * Get the number of milliseconds the system has been running. |
| 210 | * |
| 211 | * PARAMS |
| 212 | * None. |
| 213 | * |
| 214 | * RETURNS |
| 215 | * The current tick count. |
| 216 | * |
| 217 | * NOTES |
Austin English | d5de997 | 2008-03-17 15:51:39 -0500 | [diff] [blame] | 218 | * The value returned will wrap around every 2^32 milliseconds. |
| 219 | * Under Windows, tick 0 is the moment at which the system is rebooted. |
| 220 | * Under Wine, tick 0 begins at the moment the wineserver process is started. |
Alexandre Julliard | 9ad5628 | 2005-07-14 10:32:46 +0000 | [diff] [blame] | 221 | */ |
| 222 | DWORD WINAPI GetTickCount(void) |
| 223 | { |
Alexandre Julliard | 40fb7ca | 2007-07-11 14:04:54 +0200 | [diff] [blame] | 224 | return GetTickCount64(); |
Alexandre Julliard | 9ad5628 | 2005-07-14 10:32:46 +0000 | [diff] [blame] | 225 | } |