I have found out more information about the old Internet Explorer browser used on Windows XP. Useful registry keys are used by the browser to store and retrieve information.
“HKCU\\Software\\Microsoft\\Office\\10.0\\Common\\LanguageResources\\UILanguage”. This is used by the browser to get the language used by the operating system.
This registry key contains the product ID of Internet Explorer.
// Hey, they're pointing to our PID! That's cool. StrCpyN(pdwsm->szPIDRegKey, "HKLM\\Software\\Microsoft\\Internet Explorer\\Registration\\DigitalProductID", DW_MAX_PATH); |
This code sample is a section of the Internet Explorer source code. This shows the startup process of the browser.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | // // We don't want the "No disk in drive X:" requesters, so we set // the critical error mask such that calls will just silently fail // SetErrorMode(SEM_FAILCRITICALERRORS); if(StopWatchMode() & SPMODE_BROWSER) // Used to get the start of browser total download time { StopWatch_Start(SWID_BROWSER_FRAME, TEXT("Browser Frame Start"), SPMODE_BROWSER | SPMODE_DEBUGOUT); } if ( *pszCmdLine == TEXT('\"') ) { /* * Scan, and skip over, subsequent characters until * another double-quote or a null is encountered. */ while ( *++pszCmdLine && (*pszCmdLine != TEXT('\"')) ); /* * If we stopped on a double-quote (usual case), skip * over it. */ if ( *pszCmdLine == TEXT('\"') ) pszCmdLine++; } else { while (*pszCmdLine > TEXT(' ')) pszCmdLine++; } /* * Skip past any white space preceeding the second token. */ while (*pszCmdLine && (*pszCmdLine <= TEXT(' '))) { pszCmdLine++; } si.dwFlags = 0; si.cb = sizeof(si); GetStartupInfoA(&si); i = WinMainT(GetModuleHandle(NULL), NULL, (LPTSTR)pszCmdLine, si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT); #ifndef UNIX ExitThread(i); // We only come here when we are not the shell... #else // there seem to be some desirable side effect calling ExitThread on Windows ExitProcess(i); #endif return i; } // // Create a unique event name // HANDLE AppendEvent(COPYDATASTRUCT *pcds) { static DWORD dwNextID = 0; TCHAR szEvent[MAX_IEEVENTNAME]; wsprintf(szEvent, "IE-%08X-%08X", GetCurrentThreadId(), dwNextID++); HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, szEvent); if (hEvent) { // // Put the (UNICODE) event name at the end of the cds data // LPWSTR pwszBufferEvent = (LPWSTR)(((BYTE *)pcds->lpData) + pcds->cbData); #ifdef UNICODE lstrcpy(pwszBufferEvent, szEvent); #else MultiByteToWideChar(CP_ACP, 0, szEvent, -1, pwszBufferEvent, ARRAYSIZE(szEvent)); #endif pcds->cbData += (lstrlenW(pwszBufferEvent) + 1) * sizeof(WCHAR); } return hEvent; } BOOL IsCommandSwitch(LPTSTR lpszCmdLine, LPTSTR pszSwitch, BOOL fRemoveSwitch) { LPTSTR lpsz; if ((lpsz=StrStrI(lpszCmdLine, pszSwitch)) && (lpsz == lpszCmdLine)) { int cch = lstrlen(pszSwitch); if (*(lpsz+cch) == 0 || *(lpsz+cch) == TEXT(' ')) { while (*(lpsz+cch) == TEXT(' ')) cch++; if (fRemoveSwitch) { // Remove the switch by copying everything up. *lpsz=0; lstrcat(lpsz, lpsz+cch); } return TRUE; } } return FALSE; } BOOL CheckForNeedingAppCompatWindow(void) { // Which I could simply get the Process of who spawned me. For now // try hack to get the foreground window and go from there... TCHAR szClassName[80]; HWND hwnd = GetForegroundWindow(); if (hwnd && GetClassName(hwnd, szClassName, ARRAYSIZE(szClassName)) > 0) { if (lstrcmpi(szClassName, TEXT("MauiFrame")) == 0) return TRUE; } return FALSE; } // // AppCompat - Sequel NetPIM execs a browser and then waits forever // looking for a visible top level window owned by this process. // HWND CreateAppCompatWindow(HINSTANCE hinst) { HWND hwnd; static const TCHAR c_szClass[] = TEXT("IEDummyFrame"); // IE3 used "IEFrame" WNDCLASS wc = { 0, DefWindowProc, 0, 0, hinst, NULL, NULL, NULL, NULL, c_szClass }; RegisterClass(&wc); // Netmanage ECCO Pro asks to get the menu... HMENU hmenu = CreateMenu(); hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, c_szClass, TEXT(""), 0, 0x00007FF0, 0x00007FF0, 0, 0, NULL, hmenu, hinst, NULL); // Don't open SHOWDEFAULT or this turkey could end up maximized ShowWindow(hwnd, SW_SHOWNA); return hwnd; } #define USERAGENT_POST_PLATFORM_PATH_TO_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\User Agent\\Post Platform") void SetCompatModeUserAgentString(void) { HKEY hkey; const char szcompat[]=TEXT("compat"); if (ERROR_SUCCESS == RegCreateKey(HKEY_CURRENT_USER, USERAGENT_POST_PLATFORM_PATH_TO_KEY, &hkey)) { RegSetValueEx( hkey, szcompat, 0, REG_BINARY, (LPBYTE)NULL, 0); RegCloseKey(hkey); } } // Tell the user they are running in compat mode and not all the features will be available. #define IECOMPAT_REG_VAL TEXT("CompatWarningFor") void WarnCompatMode(HINSTANCE hinst) { TCHAR szFqFilename[MAX_PATH]; TCHAR szRegVal[MAX_PATH]; TCHAR szTitle[255]; TCHAR szMsg[1024]; LPTSTR szFile; GetModuleFileName(NULL, szFqFilename, ARRAYSIZE(szFqFilename)); szFile = PathFindFileName(szFqFilename); // Build up string "compatmodewarningfor <exe name>" as value for reg key lstrcpy(szRegVal, IECOMPAT_REG_VAL); lstrcat(szRegVal, szFile); LoadString(hinst, IDS_COMPATMODEWARNINGTITLE, szTitle, ARRAYSIZE(szTitle)); LoadString(hinst, IDS_COMPATMODEWARNING, szMsg, ARRAYSIZE(szMsg)); SHMessageBoxCheck(NULL, szMsg, szTitle, MB_OK, FALSE, szRegVal); } #ifdef WINNT // this is the same code that is in explorer.exe (initcab.c) #define RSA_PATH_TO_KEY TEXT("Software\\Microsoft\\Cryptography\\Defaults\\Provider\\Microsoft Base Cryptographic Provider v1.0") #define CSD_REG_PATH TEXT("System\\CurrentControlSet\\Control\\Windows") #define CSD_REG_VALUE TEXT("CSDVersion") // the signatures we are looking for in the regsitry so that we can patch up #ifdef _M_IX86 static BYTE SP3Sig[] = {0xbd, 0x9f, 0x13, 0xc5, 0x92, 0x12, 0x2b, 0x72, 0x4a, 0xba, 0xb6, 0x2a, 0xf9, 0xfc, 0x54, 0x46, 0x6f, 0xa1, 0xb4, 0xbb, 0x43, 0xa8, 0xfe, 0xf8, 0xa8, 0x23, 0x7d, 0xd1, 0x85, 0x84, 0x22, 0x6e, 0xb4, 0x58, 0x00, 0x3e, 0x0b, 0x19, 0x83, 0x88, 0x6a, 0x8d, 0x64, 0x02, 0xdf, 0x5f, 0x65, 0x7e, 0x3b, 0x4d, 0xd4, 0x10, 0x44, 0xb9, 0x46, 0x34, 0xf3, 0x40, 0xf4, 0xbc, 0x9f, 0x4b, 0x82, 0x1e, 0xcc, 0xa7, 0xd0, 0x2d, 0x22, 0xd7, 0xb1, 0xf0, 0x2e, 0xcd, 0x0e, 0x21, 0x52, 0xbc, 0x3e, 0x81, 0xb1, 0x1a, 0x86, 0x52, 0x4d, 0x3f, 0xfb, 0xa2, 0x9d, 0xae, 0xc6, 0x3d, 0xaa, 0x13, 0x4d, 0x18, 0x7c, 0xd2, 0x28, 0xce, 0x72, 0xb1, 0x26, 0x3f, 0xba, 0xf8, 0xa6, 0x4b, 0x01, 0xb9, 0xa4, 0x5c, 0x43, 0x68, 0xd3, 0x46, 0x81, 0x00, 0x7f, 0x6a, 0xd7, 0xd1, 0x69, 0x51, 0x47, 0x25, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #else // other than _M_IX86 static BYTE SP3Sig[] = {0x8a, 0x06, 0x01, 0x6d, 0xc2, 0xb5, 0xa2, 0x66, 0x12, 0x1b, 0x9c, 0xe4, 0x58, 0xb1, 0xf8, 0x7d, 0xad, 0x17, 0xc1, 0xf9, 0x3f, 0x87, 0xe3, 0x9c, 0xdd, 0xeb, 0xcc, 0xa8, 0x6b, 0x62, 0xd0, 0x72, 0xe7, 0xf2, 0xec, 0xd6, 0xd6, 0x36, 0xab, 0x2d, 0x28, 0xea, 0x74, 0x07, 0x0e, 0x6c, 0x6d, 0xe1, 0xf8, 0x17, 0x97, 0x13, 0x8d, 0xb1, 0x8b, 0x0b, 0x33, 0x97, 0xc5, 0x46, 0x66, 0x96, 0xb4, 0xf7, 0x03, 0xc5, 0x03, 0x98, 0xf7, 0x91, 0xae, 0x9d, 0x00, 0x1a, 0xc6, 0x86, 0x30, 0x5c, 0xc8, 0xc7, 0x05, 0x47, 0xed, 0x2d, 0xc2, 0x0b, 0x61, 0x4b, 0xce, 0xe5, 0xb7, 0xd7, 0x27, 0x0c, 0x9e, 0x2f, 0xc5, 0x25, 0xe3, 0x81, 0x13, 0x9d, 0xa2, 0x67, 0xb2, 0x26, 0xfc, 0x99, 0x9d, 0xce, 0x0e, 0xaf, 0x30, 0xf3, 0x30, 0xec, 0xa3, 0x0a, 0xfe, 0x16, 0xb6, 0xda, 0x16, 0x90, 0x9a, 0x9a, 0x74, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #endif // _M_IX86 void CheckForSP3RSAOverwrite( void ) { // check for them having installed NTSP3 over the top of IE4, it nukes // the RSABASE reg stuff, so we have to re-do it. (our default platform is NT + SP3, but this // problem doesn't occur on NT5, so ignore it. OSVERSIONINFO osVer; ZeroMemory(&osVer, sizeof(osVer)); osVer.dwOSVersionInfoSize = sizeof(osVer); if( GetVersionEx(&osVer) && (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osVer.dwMajorVersion == 4)) { // now check to see we are on SP3 ... DWORD dwValue = 0; DWORD dwSize = sizeof( dwValue ); if ( ERROR_SUCCESS == SHGetValue( HKEY_LOCAL_MACHINE, CSD_REG_PATH, CSD_REG_VALUE, NULL, &dwValue, &dwSize) && LOWORD( dwValue ) == 0x300 ) { BYTE rgbSig[136]; dwSize = sizeof(rgbSig); if (ERROR_SUCCESS == SHGetValue ( HKEY_LOCAL_MACHINE, RSA_PATH_TO_KEY, TEXT("Signature"), NULL, rgbSig, &dwSize)) { if ((dwSize == sizeof(SP3Sig)) && (0 == memcmp(SP3Sig, rgbSig, sizeof(SP3Sig)))) { // need to do a DLLRegisterServer on RSABase HINSTANCE hInst = LoadLibrary(TEXT("rsabase.dll")); if ( hInst ) { FARPROC pfnDllReg = GetProcAddress( hInst, "DllRegisterServer"); if ( pfnDllReg ) { __try { pfnDllReg(); } __except( EXCEPTION_EXECUTE_HANDLER) { } __endexcept } FreeLibrary( hInst ); } } } } } } #else #define CheckForSP3RSAOverwrite() #endif #define TEN_SECONDS (10 * 1000) LONG WINAPI DwExceptionFilter(LPEXCEPTION_POINTERS pep) { EXCEPTION_RECORD *per; HANDLE hFileMap = NULL; DWSharedMem *pdwsm = NULL; SECURITY_ATTRIBUTES sa; LONG lReturn = 0; // we keep local copies of these in case another thread is trashing memory // it much more likely to trash the heap than our stack HANDLE hEventDone = NULL; // event DW signals when done HANDLE hEventAlive = NULL; // heartbeat event DW signals per EVENT_TIMEOUT HANDLE hMutex = NULL; // to protect the signaling of EventDone CHAR szCommandLine[MAX_PATH * 2]; DWORD dwSize, dwType, dw; TCHAR tchURL[INTERNET_MAX_URL_LENGTH]; BOOL fDwRunning; STARTUPINFOA si; PROCESS_INFORMATION pi; // init if (pep) { per = pep->ExceptionRecord; if (EXCEPTION_BREAKPOINT == per->ExceptionCode) goto Cleanup; } // create shared memory memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, sizeof(DWSharedMem), NULL); if (hFileMap == NULL) { lReturn = 1; goto Cleanup; } pdwsm = (DWSharedMem *) MapViewOfFile(hFileMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); if (pdwsm == NULL) { lReturn = 1; goto Cleanup; } memset(pdwsm, 0, sizeof(DWSharedMem)); hEventAlive = CreateEvent(&sa, FALSE, FALSE, NULL); hEventDone = CreateEvent(&sa, FALSE, FALSE, NULL); hMutex = CreateMutex(&sa, FALSE, NULL); if (!DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &pdwsm->hProc, PROCESS_ALL_ACCESS, TRUE, 0)) { lReturn = 1; goto Cleanup; } if (hEventAlive == NULL || hEventDone == NULL || hMutex == NULL || pdwsm->hProc == NULL) { lReturn = 1; goto Cleanup; } // setup interface structure pdwsm->pid = GetCurrentProcessId(); pdwsm->tid = GetCurrentThreadId(); pdwsm->hEventAlive = hEventAlive; pdwsm->hEventDone = hEventDone; pdwsm->hMutex = hMutex; pdwsm->dwSize = sizeof(DWSharedMem); pdwsm->pep = pep; if (pep) pdwsm->eip = (DWORD_PTR) pep->ExceptionRecord->ExceptionAddress; pdwsm->bfmsoctdsOffer = MSODWRESTARTQUIT; pdwsm->lcidUI = MLGetUILanguage(); StrCpyNW(pdwsm->wzFormalAppName, L"Microsoft Internet Explorer", DW_APPNAME_LENGTH); StrCpyN(pdwsm->szRegSubPath, "Microsoft\\Office\\10.0\\Common", DW_MAX_REGSUBPATH); // Our language key? StrCpyN(pdwsm->szLCIDKeyValue, "HKCU\\Software\\Microsoft\\Office\\10.0\\Common\\LanguageResources\\UILanguage", DW_MAX_PATH); // Hey, they're pointing to our PID! That's cool. StrCpyN(pdwsm->szPIDRegKey, "HKLM\\Software\\Microsoft\\Internet Explorer\\Registration\\DigitalProductID", DW_MAX_PATH); // Okay, I'll send it there. // dwSize = INTERNET_MAX_URL_LENGTH; if (ERROR_SUCCESS == SHGetValueA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Internet Explorer\\Main", "IEWatsonURL", &dwType, tchURL, &dwSize)) { StrCpyN(pdwsm->szServer, tchURL, DW_MAX_SERVERNAME); } else { StrCpyN(pdwsm->szServer, "watson.microsoft.com", DW_MAX_SERVERNAME); } // Do not set details string. //StrCpyNW(pdwsm->wzErrorMessage, L"Internet Explorer has encountered an internal error.", DW_MAX_ERROR_CWC); // Core modules StrCpyNW(pdwsm->wzDotDataDlls, L"browseui.dll\0shdocvw.dll\0mshtml.dll\0urlmon.dll\0wininet.dll\0", DW_MAX_PATH); // This will usually be "IEXPLORE.EXE" GetModuleFileNameWrapW(NULL, pdwsm->wzModuleFileName, DW_MAX_PATH); // ok, now we don't want to accidently change this memset(&si, 0, sizeof(STARTUPINFOA)); si.cb = sizeof(STARTUPINFOA); memset(&pi, 0, sizeof(PROCESS_INFORMATION)); wnsprintfA(szCommandLine, sizeof(szCommandLine), "dw15 -x -s %u", (DWORD_PTR) hFileMap); if (CreateProcessA(NULL, szCommandLine, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { fDwRunning = TRUE; while (fDwRunning) { if (WaitForSingleObject(hEventAlive, DW_TIMEOUT_VALUE) == WAIT_OBJECT_0) { if (WaitForSingleObject(hEventDone, 1) == WAIT_OBJECT_0) { fDwRunning = FALSE; } continue; } // we timed-out waiting for DW to respond, try to quit dw = WaitForSingleObject(hMutex, DW_TIMEOUT_VALUE); if (dw == WAIT_TIMEOUT) fDwRunning = FALSE; // either DW's hung or crashed, we must carry on else if (dw == WAIT_ABANDONED) { fDwRunning = FALSE; ReleaseMutex(hMutex); } else { // DW has not woken up? if (WaitForSingleObject(hEventAlive, 1) != WAIT_OBJECT_0) // tell DW we're through waiting for it's sorry self { SetEvent(hEventDone); fDwRunning = FALSE; } else { // are we done if (WaitForSingleObject(hEventDone, 1) == WAIT_OBJECT_0) fDwRunning = FALSE; } ReleaseMutex(hMutex); } } } // end if CreateProcess succeeded Cleanup: if (hEventAlive) CloseHandle(hEventAlive); if (hEventDone) CloseHandle(hEventDone); if (hMutex) CloseHandle(hMutex); if (pdwsm) UnmapViewOfFile(pdwsm); if (hFileMap) CloseHandle(hFileMap); return lReturn; } //--------------------------------------------------------------------------- int WinMainT(HINSTANCE hinst, HINSTANCE hPrevInstance, LPTSTR lpszCmdLine, int nCmdShow) { #ifdef DEBUG CcshellGetDebugFlags(); #endif int iRet = TRUE; HWND hwndDesktop ; BOOL fNowait = FALSE; BOOL fInproc = FALSE; BOOL fEval = FALSE; #ifdef UNIX BOOL fRemote = FALSE; #endif |
And the code below is to do with the UNIX compatibility when it runs on Sun Solaris UNIX.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <stdlib.h> #include <mainwin.h> #define IEREMOTE_CMDLINE 1 #define IEREMOTECLASS TEXT("IEFrame") BOOL ConnectRemoteIE(LPTSTR pszCmdLine, HINSTANCE hInstance); BOOL IsCommandSwitch(LPTSTR lpszCmdLine, LPTSTR pszSwitch); BOOL RemoteIENewWindow(LPTSTR pszCmdLine); #if defined(UNIX) #include <sys/time.h> #include <sys/resource.h> #define INCREASE_FILEHANDLE_LIMIT \ struct rlimit rl; \ if ( 0 == getrlimit(RLIMIT_NOFILE, &rl)) { \ rl.rlim_cur = rl.rlim_max; \ setrlimit(RLIMIT_NOFILE, &rl); \ } \ #endif |
Finally, this is the iexplore\unixstuff.cpp file that contains more code to do with the UNIX compatibility for Internet Explorer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | #include "iexplore.h" #include "unixstuff.h" // // BOOL ConnectRemoteIE(LPTSTR pszCommandLine) // // This function will be called when -remote parameter is specified during the // invokation of IE. That's the same format as Netscape uses, see // http://home.netscape.com/newsref/std/x-remote.html. // For now, the only special action supported is openURL(URL), because we need // it for the NetShow. We just put it as the URL was specified as iexplorer // param. To be done - connection to the existent browser. // Returns TRUE if succeed to connect to the existent browser. // #define c_szSpace TEXT(' ') static BOOL IsOpenURL(LPCTSTR pszBeginCommand, LPCTSTR pszEndCommand, LPTSTR pszURL) { const TCHAR c_szOpenURL[] = TEXT("openURL"); const TCHAR c_szLBracket = TEXT('('); const TCHAR c_szRBracket = TEXT(')'); const TCHAR c_szSQuote = TEXT('\''); const TCHAR c_szDQuote = TEXT('\"'); LPCTSTR pszBeginURL, pszEndURL; BOOL bRet = TRUE; // Skip the leading/trailing spaces. while (*pszBeginCommand == c_szSpace) pszBeginCommand++; while ((*pszEndCommand == c_szSpace) && (pszBeginCommand <= pszEndCommand)) pszEndCommand--; // Now, parse the value and replace in the cmd line, // if there is openURL there. More formats later... if (StrCmpNI(pszBeginCommand, c_szOpenURL, lstrlen(c_szOpenURL)) || (*pszEndCommand != c_szRBracket)) { pszBeginURL = pszBeginCommand; bRet = FALSE; pszEndURL = pszEndCommand; } else{ pszBeginURL = pszBeginCommand+lstrlen(c_szOpenURL); while (*pszBeginURL == c_szSpace) pszBeginURL++; if ((*pszBeginURL != c_szLBracket) || (pszBeginURL == pszEndCommand-1)) { pszURL[0] = '\0'; return FALSE; } pszBeginURL++; pszEndURL = pszEndCommand-1; } // Skip the leading/trailing spaces. while (*pszBeginURL == c_szSpace) pszBeginURL++; while (*pszEndURL == c_szSpace) pszEndURL--; // Take off quotes. if (((*pszBeginURL == c_szSQuote) && (*pszEndURL == c_szSQuote)) || ((*pszBeginURL == c_szDQuote) && (*pszEndURL == c_szDQuote))) { while (*pszBeginURL == c_szSpace) pszBeginURL++; while (*pszEndURL == c_szSpace) pszEndURL--; if (pszBeginURL >= pszEndURL) { pszURL[0] = '\0'; return FALSE; } } StrCpyN(pszURL, pszBeginURL, (pszEndURL-pszBeginURL)/sizeof(TCHAR) +2); if (bRet) bRet = pszURL[0]; return bRet; } static BOOL ConnectExistentIE(LPCTSTR pszURL, HINSTANCE hInstance) { HWND hwnd; if (hwnd = FindWindow(IEREMOTECLASS, NULL)) { COPYDATASTRUCT cds; cds.dwData = IEREMOTE_CMDLINE; cds.cbData = pszURL ? (lstrlen(pszURL)+1)*sizeof(TCHAR) : 0; cds.lpData = pszURL; SetForegroundWindow(hwnd); SendMessage(hwnd, WM_COPYDATA, (WPARAM)WMC_DISPATCH, (LPARAM)&cds); ExitProcess(0); } return FALSE; } BOOL ConnectRemoteIE(LPTSTR pszCmdLine, HINSTANCE hInstance) { const TCHAR c_szDblQuote = TEXT('"'); const TCHAR c_szQuote = TEXT('\''); LPTSTR pszBeginRemote, pszEndRemote; LPTSTR pszBeginCommand, pszEndCommand; TCHAR szURL[INTERNET_MAX_URL_LENGTH]; TCHAR szRestCmdLine[INTERNET_MAX_URL_LENGTH * 2]; // If we start with a quote, finish with a quote. // If we start with something else, finish 1 symbol before space // or end of string. pszBeginRemote = pszBeginCommand = pszCmdLine; if (*pszBeginCommand == c_szQuote || *pszBeginCommand == c_szDblQuote) { pszEndRemote = pszEndCommand = StrChr(pszBeginCommand+1, (WORD)(*pszBeginCommand)); pszBeginCommand++; } else { pszEndCommand = StrChr(pszBeginCommand, (WORD)c_szSpace); if (pszEndCommand == NULL) pszEndCommand = pszBeginCommand+lstrlen(pszBeginCommand); pszEndRemote = pszEndCommand-1; } if ((pszEndCommand == NULL) || (lstrlen(pszBeginCommand) <= 1)) return FALSE; pszEndCommand--; // // Now, check the remote command and execute. // For now, we just replace the URL in the cmd line, // if there is openURL there. More formats later... IsOpenURL(pszBeginCommand, pszEndCommand, szURL); if (ConnectExistentIE(szURL, hInstance)) return TRUE; StrCpyN(szRestCmdLine, pszEndRemote+1, ARRAYSIZE(szRestCmdLine)); *pszBeginRemote = '\0'; StrCat(pszCmdLine, szURL); StrCat(pszCmdLine, szRestCmdLine); // No connection with an existent IE was done. return FALSE; } #if 0 #define WMC_UNIX_NEWWINDOW (WM_USER + 0x0400) BOOL RemoteIENewWindow(LPTSTR pszCmdLine) { HWND hwnd; LPTSTR pszCurrent = pszCmdLine; while (*pszCurrent == TEXT(' ')) pszCurrent++; if (*pszCurrent == TEXT('-')) return FALSE; if (hwnd = FindWindow(IEREMOTECLASS, NULL)) { COPYDATASTRUCT cds; cds.dwData = IEREMOTE_CMDLINE; cds.cbData = pszCmdLine ? (lstrlen(pszCmdLine)+1)*sizeof(TCHAR) : 0; cds.lpData = pszCmdLine; SetForegroundWindow(hwnd); SendMessage(hwnd, WM_COPYDATA, (WPARAM)WMC_UNIX_NEWWINDOW, (LPARAM)&cds); printf("Opening a new window in the currently running Internet Explorer.\n"); printf("To start a new instance of Internet Explorer, type \"iexplorer -new\".\n"); return TRUE; } return FALSE; } #endif // Entry point for Mainwin is WinMain so create this function and call // ModuleEntry() from here. #if defined(MAINWIN) EXTERN_C int _stdcall ModuleEntry(void); EXTERN_C int WINAPI WinMain( HINSTANCE hinst, HINSTANCE hprev, LPSTR lpcmdline, int cmd ) { return ModuleEntry (); } #endif |
Yet more information, this is all of the Registry keys installed by Internet Explorer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | REGEDIT4 [HKEY_CLASSES_ROOT\InternetExplorer.Application] @="Internet Explorer" [HKEY_CLASSES_ROOT\InternetExplorer.Application\CLSID] @="{0002DF01-0000-0000-C000-000000000046}" [HKEY_CLASSES_ROOT\InternetExplorer.Application\CurVer] @="InternetExplorer.Application.1" [HKEY_CLASSES_ROOT\InternetExplorer.Application\NotInsertable] @="" [HKEY_CLASSES_ROOT\InternetExplorer.Application.1] @="Internet Explorer (Ver 1.0)" [HKEY_CLASSES_ROOT\InternetExplorer.Application.1\CLSID] @="{0002DF01-0000-0000-C000-000000000046}" [HKEY_CLASSES_ROOT\InternetExplorer.Application.1\NotInsertable] @="" [HKEY_CLASSES_ROOT\CLSID\{0002DF01-0000-0000-C000-000000000046}] @="Internet Explorer(Ver 1.0)" [HKEY_CLASSES_ROOT\CLSID\{0002DF01-0000-0000-C000-000000000046}\LocalServer32] @="c:\\windows\\ie96.exe" [HKEY_CLASSES_ROOT\CLSID\{0002DF01-0000-0000-C000-000000000046}\ProgID] @="InternetExplorer.Application.1" [HKEY_CLASSES_ROOT\CLSID\{0002DF01-0000-0000-C000-000000000046}\VersionIndependentProgID] @="InternetExplorer.Application" [HKEY_CLASSES_ROOT\CLSID\{0002DF01-0000-0000-C000-000000000046}\TypeLib] @="{4547D580-355D-11CF-A9BC-00AA004AE837}" [HKEY_CLASSES_ROOT\CLSID\{0002DF01-0000-0000-C000-000000000046}\Programmable] @="" [HKEY_CLASSES_ROOT\CLSID\{0002DF01-0000-0000-C000-000000000046}\NotInsertable] @="" [HKEY_CLASSES_ROOT\TypeLib\{4547D580-355D-11CF-A9BC-00AA004AE837}] @="Internet Explorer Type Library" [HKEY_CLASSES_ROOT\TypeLib\{4547D580-355D-11CF-A9BC-00AA004AE837}\1.0] @="Internet Explorer (Ver 1.0) Type Library" [HKEY_CLASSES_ROOT\TypeLib\{4547D580-355D-11CF-A9BC-00AA004AE837}\1.0\0\win32] @="c:\windows\ie96.exe\1" |
The makefile to compile Internet Explorer for Windows XP.
!ifdef NTMAKEENV # # Build using BUILD.EXE (Do not edit this section of this file, edit SOURCES) # !INCLUDE $(NTMAKEENV)\makefile.def !endif # NTMAKEENV |
There is not much source code in the explore folder, the rest would be built into Windows XP with all of the Active Desktop and ActiveX content. But it is very interesting to look at and see how it works.
Here is some code defining the IE 2.0 icon ids. Interesting…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | //--------------------------------------------------------------------------- // Defines for the rc file. //--------------------------------------------------------------------------- // // IE 2.0 icon ids // // NOTE for IE 2.0 compatibilty these icons MUST be in this order // #define RES_ICO_FRAME 32528 #define RES_ICO_HTML 32529 #define RES_ICO_EXTRA_1 32530 #define RES_ICO_EXTRA_2 32531 #define RES_ICO_EXTRA_3 32532 #define RES_ICO_EXTRA_4 32533 #define IDI_APPEARANCE 32534 #define IDI_ADVANCED 32535 #undef IDI_HOMEPAGE #define IDI_HOMEPAGE 32536 #define IDI_GOTOURL 32537 #define IDI_FINDTEXT 32538 #define IDI_UNKNOWN_FILETYPE 32539 #define RES_ICO_JPEG 32540 #define RES_ICO_GIF 32541 #define IDI_INTERNET 32542 #define RES_ICON_FOLDER_OPEN 32543 #define RES_ICON_FOLDER_CLOSED 32544 #define RES_ICON_URL_FILE 32545 #define IDI_SECURITY 32546 #define RES_ICO_NOICON 32547 #define RES_ICO_FINDING 32548 #define RES_ICO_CONNECTING 32549 #define RES_ICO_ACCESSING 32550 #define RES_ICO_RECEIVING 32551 #define IDI_NEWS 32552 #define IDI_VRML 32553 #define IDI_MHTMLFILE 32554 // String IDS which are actually used: #define IDS_COMPATMODEWARNING 700 #define IDS_COMPATMODEWARNINGTITLE 701 #define IDS_INTERNETEXPLORER 702 // Commmand ID #define FCIDM_FIRST FCIDM_GLOBALFIRST #define FCIDM_LAST FCIDM_BROWSERLAST //--------------------------------------------------------------------------- #define FCIDM_BROWSER_FILE (FCIDM_BROWSERFIRST+0x0020) #define FCIDM_FILECLOSE (FCIDM_BROWSER_FILE+0x0001) #define FCIDM_PREVIOUSFOLDER (FCIDM_BROWSER_FILE+0x0002) #define FCIDM_ENTER (FCIDM_BROWSER_FILE+0x0003) // these aren't real menu commands, but they map to accelerators or other things #define FCIDM_NEXTCTL (FCIDM_BROWSER_FILE+0x0010) #define FCIDM_DROPDRIVLIST (FCIDM_BROWSER_FILE+0x0011) //--------------------------------------------------------------------------- #define FCIDM_VIEWTOOLBAR (FCIDM_BROWSERFIRST + 0x0010) #define FCIDM_VIEWSTATUSBAR (FCIDM_BROWSERFIRST + 0x0011) #define FCIDM_VIEWOPTIONS (FCIDM_BROWSERFIRST + 0x0012) //--------------------------------------------------------------------------- #define FCIDM_BROWSER_HELP (FCIDM_BROWSERFIRST+0x0100) #define FCIDM_HELPSEARCH (FCIDM_BROWSER_HELP+0x0001) #define FCIDM_HELPABOUT (FCIDM_BROWSER_HELP+0x0002) //---------------------------------------------------------------- #define FCIDM_BROWSER_EXPLORE (FCIDM_BROWSERFIRST + 0x0110) #define FCIDM_NAVIGATEBACK (FCIDM_BROWSER_EXPLORE+0x0001) #define FCIDM_NAVIGATEFORWARD (FCIDM_BROWSER_EXPLORE+0x0002) #define FCIDM_BROWSEROPTIONS (FCIDM_BROWSER_EXPLORE+0x0003) #define FCIDM_RECENTMENU (FCIDM_BROWSER_EXPLORE+0x0010) #define FCIDM_RECENTFIRST (FCIDM_BROWSER_EXPLORE+0x0011) #define FCIDM_RECENTLAST (FCIDM_BROWSER_EXPLORE+0x0050) #define FCIDM_FAVORITES (FCIDM_BROWSER_EXPLORE+0x0052) #define FCIDM_ADDTOFAVORITES (FCIDM_BROWSER_EXPLORE+0x0053) #define FCIDM_FAVORITEFIRST (FCIDM_BROWSER_EXPLORE+0x0055) #define FCIDM_FAVORITELAST (FCIDM_BROWSER_EXPLORE+0x0100) #define FCIDM_FAVORITE_ITEM (FCIDM_FAVORITEFIRST + 0) #define FCIDM_FAVORITECMDFIRST (FCIDM_FAVORITES) #define FCIDM_FAVORITECMDLAST (FCIDM_FAVORITELAST) #define MH_POPUPS 700 #define MH_ITEMS (800-FCIDM_FIRST) #define MH_TTBASE (MH_ITEMS - (FCIDM_LAST - FCIDM_FIRST)) #define IDS_TT_PREVIOUSFOLDER (MH_TTBASE+FCIDM_PREVIOUSFOLDER) #define IDS_TT_NAVIGATEBACK (MH_TTBASE + FCIDM_NAVIGATEBACK) #define IDS_TT_NAVIGATEFORWARD (MH_TTBASE + FCIDM_NAVIGATEFORWARD) #define IDS_TT_FAVORITES (MH_TTBASE + FCIDM_FAVORITES) #define IDS_TT_ADDTOFAVORITES (MH_TTBASE + FCIDM_ADDTOFAVORITES) // Define string ids that go into resource file #define IDS_MH_DRIVELIST (MH_ITEMS+FCIDM_DRIVELIST) #define IDS_MH_MENU_FILE (MH_ITEMS+FCIDM_MENU_FILE) #define IDS_MH_MENU_EXPLORE (MH_ITEMS+FCIDM_MENU_EXPLORE) #define IDS_MH_MENU_HELP (MH_ITEMS+FCIDM_MENU_HELP) #define IDS_MH_FILECLOSE (MH_ITEMS+FCIDM_FILECLOSE) #define IDS_MH_PREVIOUSFOLDER (MH_ITEMS+FCIDM_PREVIOUSFOLDER) #define IDS_MH_HELPSEARCH (MH_ITEMS+FCIDM_HELPSEARCH) #define IDS_MH_HELPABOUT (MH_ITEMS+FCIDM_HELPABOUT) #define IDS_MH_NAVIGATEBACK (MH_ITEMS+FCIDM_NAVIGATEBACK) #define IDS_MH_NAVIGATEBACK (MH_ITEMS+FCIDM_NAVIGATEBACK) #define IDS_MH_NAVIGATEFORWARD (MH_ITEMS+FCIDM_NAVIGATEFORWARD) #define IDS_MH_RECENTMENU (MH_ITEMS+FCIDM_RECENTMENU) #define IDS_MH_MENU_FAVORITES (MH_ITEMS+FCIDM_MENU_FAVORITES) #define IDS_MH_FAVORITES (MH_ITEMS+FCIDM_FAVORITES) #define IDS_MH_ADDTOFAVORITES (MH_ITEMS+FCIDM_ADDTOFAVORITES) #define IDS_NAVIGATEBACKTO 720 #define IDS_NAVIGATEFORWARDTO 721 #define IDS_OPTIONS 722 #define IDS_TITLE 723 #define IDS_ERROR_GOTO 724 #define IDS_NONE 725 #define IDS_NAME 726 // Used for NAME member function for fram programmability // Accelerator ID #define ACCEL_MERGE 0x100 // Menu ID #define MENU_TEMPLATE 0x100 #define MENU_FAVORITES 0x101 |
Do you think it’s possible to build a standalone executable of IE5 from the win2k source code? I built calc.exe with some minor esthetic changes, it took me a couple of days to get it done, my setup is Win7 and Visual Studio Express 2008 (I know it’s almost year 2024 by the way).
Maybe, easier than Windows XP. IE is spread across the whole OS it seems with the Active Desktop crap. But IE was on Solaris UNIX as well, I wonder if you could build it for Linux. Or would you want to?