//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1996. // // File: surrogat.cxx // // Contents: Entry point for dll surrogate process // // Synopsis: this is the entry point for a surrogate process. It must // perform the following tasks // 1. Initialize OLE (multithreaded) // 2. Create an object which implements ISurrogate, and register // it with COM via CoRegisterSurrogateEx // 3. Wait for all loaded dlls to be unloadable // 4. Uninitialize OLE // // Functions: WinMain // GetCommandLineArguments // // History: 21-May-96 t-AdamE Created // 09-Apr-98 WilfR Modified for Unified Surrogate // 07-Jul-01 EgidioS Set env variable to load server flavor // of URT when running in a server box. // //-------------------------------------------------------------------------- #include #include "csrgt.hxx" #include "surrogat.hxx" #include "srgtdeb.hxx" #include "debug.hxx" DECLARE_INFOLEVEL(Surrogate); // debug only // defined in unisrgt.idl (*.h) STDAPI CoRegisterSurrogateEx( REFGUID rguidProcess, ISurrogate* pSurrogate ); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { GUID guidProcessID; // will hold the ProcessID of this surrogate CHAR rgargv[cCmdLineArguments][MAX_PATH + 1]; LPSTR argv[] = {rgargv[iProcessIDArgument]}; HRESULT hr; LPSTR pProcessID; WCHAR wszProcessID[MAX_GUIDSTR_LEN + 1]; #if DBG == 1 // check registry flags to break on launch (for debug) if( DebugFlags::DebugBreakOnLaunchDllHost() ) { DebugBreak(); } #endif // command line format should be: // New Style: (/ProcessID:) // Old style: ({appid guid}) if(GetCommandLineArguments(lpCmdLine, argv,cCmdLineArguments,MAX_PATH) < 1) { Win4Assert( !"GetCommandLineArguments failed" ); return 0; } // First Try new Style // separate the cmdline switch from the cmdline arg (at the ':') for( pProcessID = argv[iProcessIDArgument]; *pProcessID != 0; pProcessID++ ) { // this will zap the colon if(*pProcessID == ':') { *pProcessID++ = '\0'; break; } } #if 0 // verify that the cmdline switch is what we are looking for if((*pProcessID == 0) || (lstrcmpiA(argv[iProcessIDArgument], szProcessIDSwitch) != 0)) { Win4Assert( !"Couldn't find /ProcessID:" ); return 0; } #else if((*pProcessID == 0) || (lstrcmpiA(argv[iProcessIDArgument], szProcessIDSwitch) != 0)) pProcessID = argv[iProcessIDArgument]; #endif // we need a unicode string in order to get a guid, so convert // the ansi clsid string to unicode if(!(MultiByteToWideChar(CP_ACP, 0, pProcessID, lstrlenA(pProcessID) + 1, wszProcessID, MAX_GUIDSTR_LEN + 1))) { Win4Assert( !"MultiByteToWideChar failed" ); return 0; } // convert the ProcessID from a string to a guid if(FAILED(CLSIDFromString(wszProcessID,&guidProcessID))) { Win4Assert( !"CLSIDFromString failed" ); return 0; } if(FAILED(CoInitializeEx(NULL,COINIT_MULTITHREADED))) { Win4Assert( !"CoInitEx failed" ); return 0; } // HACK: If Whistler server and above, force the process to use .NET mscorsvr.dll. // For server apps. this version of the .NET runtime performs better. if (IsServerOS()) { SetEnvironmentVariableW(L"ComPlus_BuildFlavor", L"SVR"); } // Hand the thread to OLE for the duration hr = CoRegisterSurrogateEx(guidProcessID, NULL); CoUninitialize(); // Because some of our threads don't exit cleanly, and can AV // in those situations, we don't die gracefully. TerminateProcess(GetCurrentProcess(), 0); return 0; } //+--------------------------------------------------------------------------- // // Function: GetCommandLineArguments // // Synopsis: Parses a the application's command line into a format // similar to the // argv parameter of the entry point main for console apps // Spaces are the delimiters // // Arguments: [rgwszArgs] -- an array of pointers to allocated Unicode // buffers // [cMaxArgs] -- This is the size of the rgwszArgs array (the // maximum number of arguments the array can hold). // [cMaxArgLen] -- The maximum size of each buffer // // Returns: if successful, the function returns the number of arguments // parsed from the command line. If the length of any argument // exceeds cMaxArgLen, the function fails and returns 0. // // The function quits parsing and returns as soon as either of // the following conditions is met: // 1. It reaches the end of the string, or // 2. It parses cMaxArgs arguments. // // Notes: does not work with quoted arguments // // History: 6-21-96 t-Adame Created // //---------------------------------------------------------------------------- // REVIEW: when we had several commandline parameters this function was // justified, but now that the Surrogate has only one parameter, is all this // really necessary? int GetCommandLineArguments(LPSTR szCmdLine, LPSTR rgszArgs[], int cMaxArgs, int cMaxArgLen) { int cchlen = lstrlenA(szCmdLine); int cArgsRetrieved = 0; int ichStart = 0; for(int ich = 0;ich < cchlen; ich++) { if(ichStart > cMaxArgLen) { return 0; } CHAR chcur = *(szCmdLine++); if(chcur == ' ')// REVIEW: no tab delimiting -- is this good? { if(ichStart) { rgszArgs[cArgsRetrieved++][ichStart] = '\0'; ichStart = 0; if(cArgsRetrieved == cMaxArgs) { return cArgsRetrieved; } } } else { rgszArgs[cArgsRetrieved][ichStart++] = chcur; } } if(ichStart) { rgszArgs[cArgsRetrieved][ichStart] = '\0'; cArgsRetrieved++; } return cArgsRetrieved; } //+--------------------------------------------------------------------------- // // Function: IsServerOS // // Synopsis: Checks if we are running on a Whistler server machine. // // Arguments: None. // // Returns: TRUE if Whistler server/advanced/datacenter. // FALSE otherwise. // // Notes: None. // // History: 7-12-01 egidios Created // //---------------------------------------------------------------------------- BOOL IsServerOS(void) { // Note the following structure is only supported for NT 5.0 OSVERSIONINFOEX osverex; osverex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); if (::GetVersionEx((OSVERSIONINFO*)&osverex)) { if (osverex.dwPlatformId == VER_PLATFORM_WIN32_NT) { if ((osverex.dwMajorVersion == 5 && osverex.dwMinorVersion >= 1) || // >= WinXP (osverex.dwMajorVersion > 5)) { if (osverex.wSuiteMask & VER_SUITE_PERSONAL) { return FALSE; } else if (osverex.wProductType == VER_NT_WORKSTATION) { return FALSE; } else if (osverex.wProductType == VER_NT_SERVER) { return TRUE; } else if (osverex.wSuiteMask & VER_SUITE_ENTERPRISE) { return TRUE; } else if (osverex.wSuiteMask & VER_SUITE_DATACENTER) { return TRUE; } } } } return FALSE; }