BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { INITCOMMONCONTROLSEX initCommonControlsEx; ACTCTX actCtx; UNREFERENCED_PARAMETER(lpReserved); g_hModuleInstance = (HINSTANCE) hModule; switch (dwReason) { case DLL_PROCESS_ATTACH: if (!g_hStiInstance) { g_hStiInstance = LoadLibrary(TEXT("sti.dll")); } if (!g_hStiCiInstance) { g_hStiCiInstance = LoadLibrary(TEXT("sti_ci.dll")); } if (!g_hWiaDefInstance) { g_hWiaDefInstance = LoadLibrary(TEXT("wiadefui.dll")); } // fall through to thread attachment case DLL_THREAD_ATTACH: if (!g_bCommonControls) { ZeroMemory(&initCommonControlsEx, sizeof(INITCOMMONCONTROLSEX)); initCommonControlsEx.dwSize = sizeof(INITCOMMONCONTROLSEX); initCommonControlsEx.dwICC = ICC_STANDARD_CLASSES | ICC_USEREX_CLASSES; g_bCommonControls = InitCommonControlsEx(&initCommonControlsEx); } if (!g_hActivationContext) { ZeroMemory(&actCtx, sizeof(ACTCTX)); actCtx.cbSize = sizeof(ACTCTX); actCtx.dwFlags = ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID; actCtx.hModule = hModule; actCtx.lpResourceName = TEXT("MANIFEST"); g_hActivationContext = CreateActCtx(&actCtx); } break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: if (g_hWiaDefInstance) { FreeLibrary(g_hWiaDefInstance); g_hWiaDefInstance = NULL; } if (g_hStiCiInstance) { FreeLibrary(g_hStiCiInstance); g_hStiCiInstance = NULL; } if (g_hStiInstance) { FreeLibrary(g_hStiInstance); g_hStiInstance = NULL; } break; } return TRUE; }
static ULONG_PTR wxPySetActivationContext() { OSVERSIONINFO info; wxZeroMemory(info); info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&info); if (info.dwMajorVersion < 5) return 0; ULONG_PTR cookie = 0; HANDLE h; ACTCTX actctx; TCHAR modulename[MAX_PATH]; GetModuleFileName(wxGetInstance(), modulename, MAX_PATH); wxZeroMemory(actctx); actctx.cbSize = sizeof(actctx); actctx.lpSource = modulename; actctx.lpResourceName = MAKEINTRESOURCE(2); actctx.hModule = wxGetInstance(); actctx.dwFlags = ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID; h = CreateActCtx(&actctx); if (h == INVALID_HANDLE_VALUE) { wxLogLastError(wxT("CreateActCtx")); return 0; } if (! ActivateActCtx(h, &cookie)) wxLogLastError(wxT("ActivateActCtx")); return cookie; }
/* Open file as memory-mapped PE image IN: path - file path RETURN: Address of file mapping */ void* CFileProjection::Project( const std::wstring& path ) { Release(); ACTCTX act = {0}; act.cbSize = sizeof(act); act.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; act.lpSource = path.c_str(); act.lpResourceName = MAKEINTRESOURCE(2); m_hctx = CreateActCtx(&act); if(m_hctx == INVALID_HANDLE_VALUE) { act.lpResourceName = MAKEINTRESOURCE(1); m_hctx = CreateActCtx(&act); } m_hFile = CreateFile(path.c_str(), FILE_GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL); if(m_hFile != INVALID_HANDLE_VALUE) { // Try mapping as image m_hMapping = CreateFileMapping(m_hFile, NULL, SEC_IMAGE | PAGE_READONLY, 0, 0, NULL); if(m_hMapping && m_hMapping != INVALID_HANDLE_VALUE) { m_pData = MapViewOfFile(m_hMapping, FILE_MAP_READ, 0, 0, 0); } // Map as simple datafile else { m_isPlainData = true; m_hMapping = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL); if(m_hMapping && m_hMapping != INVALID_HANDLE_VALUE) m_pData = MapViewOfFile(m_hMapping, FILE_MAP_READ, 0, 0, 0); } } return m_pData; }
int CreateActContext(char *workpath, char *thisfile) { char manifestpath[PATH_MAX]; char basename[PATH_MAX]; ACTCTX ctx; BOOL activated; HANDLE k32; HANDLE (WINAPI *CreateActCtx)(PACTCTX pActCtx); BOOL (WINAPI *ActivateActCtx)(HANDLE hActCtx, ULONG_PTR *lpCookie); // If not XP, nothing to do -- return OK if (!IsXPOrLater()) return 1; /* Setup activation context */ pyi_path_basename(basename, thisfile); pyi_path_join(manifestpath, workpath, basename); strcat(manifestpath, ".manifest"); VS("LOADER: manifestpath: %s\n", manifestpath); k32 = LoadLibrary("kernel32"); CreateActCtx = (void*)GetProcAddress(k32, "CreateActCtxA"); ActivateActCtx = (void*)GetProcAddress(k32, "ActivateActCtx"); if (!CreateActCtx || !ActivateActCtx) { VS("LOADER: Cannot find CreateActCtx/ActivateActCtx exports in kernel32.dll\n"); return 0; } ZeroMemory(&ctx, sizeof(ctx)); ctx.cbSize = sizeof(ACTCTX); ctx.lpSource = manifestpath; hCtx = CreateActCtx(&ctx); if (hCtx != INVALID_HANDLE_VALUE) { VS("LOADER: Activation context created\n"); activated = ActivateActCtx(hCtx, &actToken); if (activated) { VS("LOADER: Activation context activated\n"); return 1; } } hCtx = INVALID_HANDLE_VALUE; VS("LOADER: Error activating the context\n"); return 0; }
bool Create( PCACTCTX pactctx ) { ASSERT( pactctx != NULL ); if ( pactctx == NULL ) { return false; } ASSERT( m_hCtxt == INVALID_HANDLE_VALUE ); if ( m_hCtxt != INVALID_HANDLE_VALUE ) { return false; } return ( ( m_hCtxt = CreateActCtx( pactctx ) ) != INVALID_HANDLE_VALUE ); }
Win32UIBinding::Win32UIBinding(Host *host) : UIBinding(host) { // We're not using registration-free COM because it requires that // the DLL be in a subdirectory of the exe. Use Activation Context // API instead. We just need to point it to the .manifest file as below. ACTCTX actctx; ZeroMemory(&actctx, sizeof(actctx)); actctx.cbSize = sizeof(actctx); std::string source = host->GetRuntimePath(); source = FileUtils::Join(source.c_str(), "WebKit.manifest", NULL); actctx.lpSource = source.c_str(); // Path to the Side-by-Side Manifest File this->pActCtx = CreateActCtx(&actctx); ActivateActCtx(pActCtx, &this->lpCookie); }
int CreateActContext(const char *manifestpath) { wchar_t * manifestpath_w; ACTCTXW ctx; BOOL activated; HANDLE k32; HANDLE (WINAPI * CreateActCtx)(PACTCTXW pActCtx); BOOL (WINAPI * ActivateActCtx)(HANDLE hActCtx, ULONG_PTR * lpCookie); /* Setup activation context */ VS("LOADER: manifestpath: %s\n", manifestpath); manifestpath_w = pyi_win32_utils_from_utf8(NULL, manifestpath, 0); k32 = LoadLibraryA("kernel32"); CreateActCtx = (void*)GetProcAddress(k32, "CreateActCtxW"); ActivateActCtx = (void*)GetProcAddress(k32, "ActivateActCtx"); if (!CreateActCtx || !ActivateActCtx) { VS("LOADER: Cannot find CreateActCtx/ActivateActCtx exports in kernel32.dll\n"); return 0; } ZeroMemory(&ctx, sizeof(ctx)); ctx.cbSize = sizeof(ACTCTX); ctx.lpSource = manifestpath_w; ctx.dwFlags = ACTCTX_FLAG_SET_PROCESS_DEFAULT; hCtx = CreateActCtx(&ctx); free(manifestpath_w); if (hCtx != INVALID_HANDLE_VALUE) { VS("LOADER: Activation context created\n"); activated = ActivateActCtx(hCtx, &actToken); if (activated) { VS("LOADER: Activation context activated\n"); return 1; } } hCtx = INVALID_HANDLE_VALUE; VS("LOADER: Error activating the context: ActivateActCtx: \n%s\n", GetWinErrorString(0)); return 0; }
__forceinline HANDLE WINAPI GetActCtx( HMODULE hModule, PCTSTR pszResourceName ) { // Wraps away the silliness of CreateActCtx, including the fact that // it will fail if you do not provide a valid path string even if you // supply a valid module handle, which is quite silly since the path is // just going to get translated into a module handle anyway by the API. ACTCTX ctx; TCHAR szModule[MAX_PATH << 1]; GetModuleFileName(hModule, szModule, countof(szModule)); ctx.cbSize = sizeof(ctx); ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; ctx.lpSource = szModule; ctx.lpResourceName = pszResourceName; ctx.hModule = hModule; return(CreateActCtx(&ctx)); }
bool CPython::init() { // // Initialize the python environment // std::wstring path; int iRslt = 0; DWORD nrslt = 0; std::vector<wchar> vetbuf; wchar buffer[MAX_PATH+1] = {0}; // First of all, get the python path from options . for (; GetOption(text("Python Path"), path); ) { nrslt = ::GetFullPathName ( // ... path.c_str(), _countof(buffer), buffer, nullptr ); if (nrslt == 0) { path.clear(); break; } if (nrslt < _countof(buffer)) { path = buffer; break; } vetbuf.resize(nrslt+1); // Allocate buffer ... nrslt = ::GetFullPathName ( // ... path.c_str(), vetbuf.size(), vetbuf.data(), nullptr ); if (!nrslt || nrslt >= vetbuf.size()) path.clear(); else path.assign(vetbuf.begin(), vetbuf.end()); break; } // Use the directory of the exe file if we fail to get python // path from options. for (std::size_t pos = 0; path.length() <= 0; ) { nrslt = GetModuleFileName ( // Try the first time ....... nullptr, buffer, _countof(buffer) ); if (nrslt == 0) { path.clear(); break; } if (nrslt < _countof(buffer)) { path = buffer; pos = path.find_last_not_of(text("\\/")); pos = path.find_last_of(text("\\/"),pos); path.replace( pos, -1, text("\\python")); break; } vetbuf.resize(nrslt*2); // Allocate buffer .......... nrslt = GetModuleFileName ( // Try the second time ...... nullptr, vetbuf.data(), vetbuf.size() ); if (nrslt != 0 && nrslt <= vetbuf.size()) { path.assign(vetbuf.begin(), vetbuf.end()); pos = path.find_last_not_of(text("\\/")); pos = path.find_last_of(text("\\/"),pos); path.replace( pos, -1, text("\\python")); } else path.clear(); break; } // Use current directory if we still can't get the python path . for (; path.length() <= 0; ) { nrslt = ::GetCurrentDirectory(_countof(buffer), buffer); if (nrslt == 0) { path.clear(); break; } if (nrslt < _countof(buffer)) { path = buffer; path += text("\\python"); } vetbuf.resize(nrslt+1); // Allocate buffer ... nrslt = ::GetCurrentDirectory(vetbuf.size(),vetbuf.data()); if (nrslt != 0 && nrslt <= vetbuf.size()) { path.assign(vetbuf.begin(), vetbuf.end()); path.append(text("\\python")); } else path.clear(); break; } // We return false if we still can't get the python path ... if(path.length()<=0) return false; path.push_back(text('\\')); // Now, We overwrite the environment variable PYTHONHOME.. // It's not a necessuary operation .. ::SetEnvironmentVariable(text("PYTHONHOME"), path.c_str()); // Locate the python kernel file "pythonxx.dll" .. WIN32_FIND_DATA fData = {0}; HANDLE hFile = nullptr; hFile = FindFirstFile((path+text("*.dll")).c_str(), &fData); if (hFile != INVALID_HANDLE_VALUE) { do { if (fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; // We skip all directory . _wcslwr_s(fData.cFileName, _countof(fData.cFileName)); if (wcsstr(fData.cFileName, text("python"))) break; else fData.cFileName[0] = text('\0'); } while (FindNextFile(hFile, &fData)); FindClose(hFile); // Finish finding .. } else fData.cFileName[0] = text('\0'); /// // Now, initialize all python interface dynamically. // The reason we query python interface dynamically is to // make sure our plugin can work without python .. /// m_pyModule = ::GetModuleHandle(fData.cFileName); if (m_pyModule == nullptr) { m_pyModule = ::LoadLibrary((path+fData.cFileName).c_str()); if (m_pyModule == nullptr) { m_pyModule = ::GetModuleHandle(text("python27.dll")); if (m_pyModule == nullptr) { m_pyModule = ::LoadLibrary(text("python27.dll")); if (m_pyModule == nullptr) return false; } } } if ( (Py_Finalize = reinterpret_cast<py_finalize>( ::GetProcAddress(m_pyModule, "Py_Finalize") )) == nullptr ) return false; if ( (Py_Initialize = reinterpret_cast<py_initialize>( ::GetProcAddress(m_pyModule, "Py_Initialize") )) == nullptr ) return false; if ( (Py_SetPythonHome = reinterpret_cast<py_setpythonhome>( ::GetProcAddress(m_pyModule, "Py_SetPythonHome") )) == nullptr ) return false; if ( (Py_SetProgramName = reinterpret_cast<py_setprogramname>( ::GetProcAddress(m_pyModule, "Py_SetProgramName") )) == nullptr ) return false; if ( (PyFile_AsFile = reinterpret_cast<pyfile_asfile>( ::GetProcAddress(m_pyModule, "PyFile_AsFile") )) == nullptr ) return false; if ( (PyFile_FromFile = reinterpret_cast<pyfile_fromfile>( ::GetProcAddress(m_pyModule, "PyFile_FromFile") )) == nullptr ) return false; if ( (PyFile_FromString = reinterpret_cast<pyfile_fromstring>( ::GetProcAddress(m_pyModule, "PyFile_FromString") )) == nullptr ) return false; if ( (PyEval_InitThreads = reinterpret_cast<pyeval_initthreads>( ::GetProcAddress(m_pyModule, "PyEval_InitThreads") )) == nullptr ) return false; if ( (PySys_SetArgv = reinterpret_cast<pysys_setargv>( ::GetProcAddress(m_pyModule, "PySys_SetArgv") )) == nullptr ) return false; if ( (PySys_GetObject = reinterpret_cast<pysys_getobject>( ::GetProcAddress(m_pyModule, "PySys_GetObject") )) == nullptr ) return false; if ( (PySys_SetObject = reinterpret_cast<pysys_setobject>( ::GetProcAddress(m_pyModule, "PySys_SetObject") )) == nullptr ) return false; if ( (PyObject_SetAttrString = reinterpret_cast<pyobject_setattrstring>( ::GetProcAddress(m_pyModule, "PyObject_SetAttrString") )) == nullptr ) return false; if ( (PyImport_ImportModule = reinterpret_cast<pyimport_importmodule>( ::GetProcAddress(m_pyModule, "PyImport_ImportModule") )) == nullptr ) return false; if ( (PyImport_AddModule = reinterpret_cast<pyimport_addmodule>( ::GetProcAddress(m_pyModule, "PyImport_AddModule") )) == nullptr ) return false; if ( (PyRun_SimpleString = reinterpret_cast<pyrun_simplestring>( ::GetProcAddress(m_pyModule, "PyRun_SimpleString") )) == nullptr ) return false; if ( (PyRun_SimpleStringFlags = reinterpret_cast<pyrun_simplestringflags>( ::GetProcAddress(m_pyModule, "PyRun_SimpleStringFlags") )) == nullptr ) return false; if ( (PyRun_SimpleFile = reinterpret_cast<pyrun_simplefile>( ::GetProcAddress(m_pyModule, "PyRun_SimpleFile") )) == nullptr ) return false; /*if ( (PyRun_SimpleFileFlags = reinterpret_cast<pyrun_simplefileflags>( ::GetProcAddress(m_pyModule, "PyRun_SimpleFileFlags") )) == nullptr ) return false;*/ if ( (PyRun_SimpleFileEx = reinterpret_cast<pyrun_simplefileex>( ::GetProcAddress(m_pyModule, "PyRun_SimpleFileEx") )) == nullptr ) return false; if ( (PyRun_SimpleFileExFlags = reinterpret_cast<pyrun_simplefileexflags>( ::GetProcAddress(m_pyModule, "PyRun_SimpleFileExFlags") )) == nullptr ) return false; // Initialize the python environment, prepare the hooks //if (Py_SetPythonHome) Py_SetPythonHome(cvt.to_bytes(path).c_str()); //if (Py_SetProgramName) Py_SetProgramName(cvt.to_bytes(buffer).c_str()); if (Py_Initialize) Py_Initialize(); if (PyEval_InitThreads) PyEval_InitThreads(); // ... /// // Now, initialize all MSVCR90 interface dynamically. /// ACTCTX ctx = {sizeof(ACTCTX), 0}; ULONG_PTR actToken = 0; ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID|ACTCTX_FLAG_HMODULE_VALID; ctx.hModule = m_pyModule; ctx.lpResourceName = MAKEINTRESOURCE(2); HANDLE hCtx = CreateActCtx(&ctx); if(hCtx != INVALID_HANDLE_VALUE) { if ( ActivateActCtx(hCtx, &actToken) ) { m_vcModule = ::GetModuleHandle(text("MSVCR90.dll")); if (m_vcModule == NULL) { m_vcModule = ::LoadLibrary(text("MSVCR90.dll")); if (m_vcModule == NULL) return false; } if ( (open_osfhandle = reinterpret_cast<__open_osfhandle>( ::GetProcAddress(m_vcModule, "_open_osfhandle") )) == nullptr ) return false; if ( (setvbuf = reinterpret_cast<__setvbuf>( ::GetProcAddress(m_vcModule, "setvbuf") )) == nullptr ) return false; if ( (fdopen = reinterpret_cast<__fdopen>( ::GetProcAddress(m_vcModule, "_fdopen") )) == nullptr ) return false; if ( (fclose = reinterpret_cast<__fclose>( ::GetProcAddress(m_vcModule, "fclose") )) == nullptr ) return false; // Deactive active context after finished .. DeactivateActCtx(0, actToken); } // Now close context ... ReleaseActCtx(hCtx); } return true; // All done, return true ... }
bool GMPLoaderImpl::Load(const char* aLibPath, uint32_t aLibPathLen, char* aOriginSalt, uint32_t aOriginSaltLen, const GMPPlatformAPI* aPlatformAPI) { std::string nodeId; #ifdef HASH_NODE_ID_WITH_DEVICE_ID if (aOriginSaltLen > 0) { string16 deviceId; int volumeId; if (!rlz_lib::GetRawMachineId(&deviceId, &volumeId)) { return false; } SHA256Context ctx; SHA256_Begin(&ctx); SHA256_Update(&ctx, (const uint8_t*)aOriginSalt, aOriginSaltLen); SHA256_Update(&ctx, (const uint8_t*)deviceId.c_str(), deviceId.size() * sizeof(string16::value_type)); SHA256_Update(&ctx, (const uint8_t*)&volumeId, sizeof(int)); uint8_t digest[SHA256_LENGTH] = {0}; unsigned int digestLen = 0; SHA256_End(&ctx, digest, &digestLen, SHA256_LENGTH); // Overwrite all data involved in calculation as it could potentially // identify the user, so there's no chance a GMP can read it and use // it for identity tracking. memset(&ctx, 0, sizeof(ctx)); memset(aOriginSalt, 0, aOriginSaltLen); volumeId = 0; memset(&deviceId[0], '*', sizeof(string16::value_type) * deviceId.size()); deviceId = L""; if (!rlz_lib::BytesToString(digest, SHA256_LENGTH, &nodeId)) { return false; } // We've successfully bound the origin salt to node id. // rlz_lib::GetRawMachineId and/or the system functions it // called could have left user identifiable data on the stack, // so carefully zero the stack down to the guard page. uint8_t* top; uint8_t* bottom; if (!GetStackAfterCurrentFrame(&top, &bottom)) { return false; } assert(top >= bottom); // Inline instructions equivalent to RtlSecureZeroMemory(). // We can't just use RtlSecureZeroMemory here directly, as in debug // builds, RtlSecureZeroMemory() can't be inlined, and the stack // memory it uses would get wiped by itself running, causing crashes. for (volatile uint8_t* p = (volatile uint8_t*)bottom; p < top; p++) { *p = 0; } } else #endif { nodeId = std::string(aOriginSalt, aOriginSalt + aOriginSaltLen); } #if defined(XP_WIN) && defined(MOZ_SANDBOX) // If the GMP DLL is a side-by-side assembly with static imports then the DLL // loader will attempt to create an activation context which will fail because // of the sandbox. If we create an activation context before we start the // sandbox then this one will get picked up by the DLL loader. int pathLen = MultiByteToWideChar(CP_ACP, 0, aLibPath, -1, nullptr, 0); if (pathLen == 0) { return false; } wchar_t* widePath = new wchar_t[pathLen]; if (MultiByteToWideChar(CP_ACP, 0, aLibPath, -1, widePath, pathLen) == 0) { delete[] widePath; return false; } ACTCTX actCtx = { sizeof(actCtx) }; actCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; actCtx.lpSource = widePath; actCtx.lpResourceName = ISOLATIONAWARE_MANIFEST_RESOURCE_ID; ScopedActCtxHandle actCtxHandle(CreateActCtx(&actCtx)); delete[] widePath; #endif // Start the sandbox now that we've generated the device bound node id. // This must happen after the node id is bound to the device id, as // generating the device id requires privileges. if (mSandboxStarter) { mSandboxStarter->Start(aLibPath); } // Load the GMP. PRLibSpec libSpec; libSpec.value.pathname = aLibPath; libSpec.type = PR_LibSpec_Pathname; mLib = PR_LoadLibraryWithFlags(libSpec, 0); if (!mLib) { return false; } GMPInitFunc initFunc = reinterpret_cast<GMPInitFunc>(PR_FindFunctionSymbol(mLib, "GMPInit")); if (!initFunc) { return false; } if (initFunc(aPlatformAPI) != GMPNoErr) { return false; } GMPSetNodeIdFunc setNodeIdFunc = reinterpret_cast<GMPSetNodeIdFunc>(PR_FindFunctionSymbol(mLib, "GMPSetNodeId")); if (setNodeIdFunc) { setNodeIdFunc(nodeId.c_str(), nodeId.size()); } mGetAPIFunc = reinterpret_cast<GMPGetAPIFunc>(PR_FindFunctionSymbol(mLib, "GMPGetAPI")); if (!mGetAPIFunc) { return false; } return true; }
int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow ) { int argc; TCHAR szMsg[RC_STRING_MAX_SIZE]; LPTSTR *argv; LPTSTR lptCmdLine,lptDllName,lptFuncName,lptMsgBuffer; LPSTR lpFuncName,lpaCmdLine; LPWSTR lpwCmdLine; HMODULE hDll; DllWinMainW fnDllWinMainW; DllWinMainA fnDllWinMainA; HWND hWindow; int i; size_t nStrLen; ACTCTXW ActCtx = {sizeof(ACTCTX), ACTCTX_FLAG_RESOURCE_NAME_VALID}; HANDLE hActCtx; ULONG_PTR cookie; BOOL bActivated; // Get command-line in argc-argv format argv = CommandLineToArgv(GetCommandLine(),&argc); // Skip all beginning arguments starting with a slash (/) for (i = 1; i < argc; i++) if (*argv[i] != _T('/')) break; // If no dll was specified, there is nothing to do if (i >= argc) { if (argv) free(argv); return 0; } lptDllName = argv[i++]; // The next argument, which specifies the name of the dll function, // can either have a comma between it and the dll filename or a space. // Using a comma here is the preferred method if (i < argc) lptFuncName = argv[i++]; else lptFuncName = _T(""); // If no function name was specified, nothing needs to be done if (!*lptFuncName) { if (argv) free(argv); return 0; } // The rest of the arguments will be passed to dll function if (i < argc) lptCmdLine = argv[i]; else lptCmdLine = _T(""); ActCtx.lpSource = lptDllName; ActCtx.lpResourceName = (LPCWSTR)123; hActCtx = CreateActCtx(&ActCtx); bActivated = (hActCtx != INVALID_HANDLE_VALUE ? ActivateActCtx(hActCtx, &cookie) : FALSE); // Everything is all setup, so load the dll now hDll = LoadLibrary(lptDllName); if (hDll) { nStrLen = _tcslen(lptFuncName); // Make a non-unicode version of the function name, // since that is all GetProcAddress accepts lpFuncName = DuplicateToMultiByte(lptFuncName,nStrLen + 2); #ifdef UNICODE lpFuncName[nStrLen] = 'W'; lpFuncName[nStrLen+1] = 0; // Get address of unicode version of the dll function if it exists fnDllWinMainW = (DllWinMainW)GetProcAddress(hDll,lpFuncName); fnDllWinMainA = 0; if (!fnDllWinMainW) { // If no unicode function was found, get the address of the non-unicode function lpFuncName[nStrLen] = 'A'; fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName); if (!fnDllWinMainA) { // If first non-unicode function was not found, get the address // of the other non-unicode function lpFuncName[nStrLen] = 0; fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName); } } #else // Get address of non-unicode version of the dll function if it exists fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName); fnDllWinMainW = 0; if (!fnDllWinMainA) { // If first non-unicode function was not found, get the address // of the other non-unicode function lpFuncName[nStrLen] = 'A'; lpFuncName[nStrLen+1] = 0; fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName); if (!fnDllWinMainA) { // If non-unicode function was not found, get the address of the unicode function lpFuncName[nStrLen] = 'W'; fnDllWinMainW = (DllWinMainW)GetProcAddress(hDll,lpFuncName); } } #endif free(lpFuncName); if (!RegisterBlankClass(hInstance, hPrevInstance)) { FreeLibrary(hDll); if (bActivated) DeactivateActCtx(0, cookie); return 0; } // Create a window so we can pass a window handle to // the dll function; this is required hWindow = CreateWindowEx(0,rundll32_wclass,rundll32_wtitle,0,CW_USEDEFAULT,0,CW_USEDEFAULT,0,0,0,hInstance,0); if (fnDllWinMainW) { // Convert the command-line string to unicode and call the dll function lpwCmdLine = ConvertToWideChar(lptCmdLine); fnDllWinMainW(hWindow,hInstance,lpwCmdLine,nCmdShow); FreeConvertedWideChar(lpwCmdLine); } else if (fnDllWinMainA) { // Convert the command-line string to ansi and call the dll function lpaCmdLine = ConvertToMultiByte(lptCmdLine); fnDllWinMainA(hWindow,hInstance,lpaCmdLine,nCmdShow); FreeConvertedMultiByte(lpaCmdLine); } else { // The specified dll function was not found; display an error message GetModuleTitle(); LoadString( GetModuleHandle(NULL), IDS_MissingEntry, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); lptMsgBuffer = (LPTSTR)malloc((_tcslen(szMsg) - 4 + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); _stprintf(lptMsgBuffer,szMsg,lptFuncName,lptDllName); MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONERROR); free(lptMsgBuffer); } DestroyWindow(hWindow); UnregisterClass(rundll32_wclass,hInstance); // The dll function has finished executing, so unload it FreeLibrary(hDll); } else { // The dll could not be loaded; display an error message GetModuleTitle(); LoadString( GetModuleHandle(NULL), IDS_DllNotLoaded, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); lptMsgBuffer = (LPTSTR)malloc((_tcslen(szMsg) - 2 + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); _stprintf(lptMsgBuffer,szMsg,lptDllName); MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONERROR); free(lptMsgBuffer); } if (bActivated) DeactivateActCtx(0, cookie); if (argv) free(argv); return 0; /* rundll32 always returns 0! */ }