Windows工程下关于强制更新代码的解读

sdologinentry.dll与sdologinentry64.dll动态库关于执行强制更新的解释

  • 函数入口: int WINAPI igwInitialize(DWORD dwSdkVersion, const AppInfo* pAppInfo)
C++ 复制代码
int WINAPI igwInitialize(DWORD dwSdkVersion, const AppInfo* pAppInfo)
{
	TRACET();

	TCHAR path[32768*2] = {0};
	DWORD len = GetEnvironmentVariable(_T("PATH"), path, _countof(path));

	TCHAR buffer[MAX_PATH] = {0};
	GetModuleFileName(g_hModule, buffer, _countof(buffer));

	_stprintf(path+len, _T(";%s\\..\\sdologin\\"), buffer);

	SetEnvironmentVariable(_T("PATH"), path);

	AppInfo* pInfo = (AppInfo*)pAppInfo;

	// Skip update process or not
	wchar_t buffer2[MAX_PATH] = {0};
	wchar_t path2[MAX_PATH*2] = {0};
	GetModuleFileNameW(g_hModule, buffer2, _countof(buffer2));
	swprintf_s(path2, _countof(path2), L"%s\\..\\sdologin\\", buffer2);

	LicenseManager::Initial(path2);
	bool bExpired = LicenseManager::GetInstance()->GetValue<bool>("Expiration");
	bool bSkipUpdate = LicenseManager::GetInstance()->GetValue<bool>("SkipUpdate");

	if (!(bExpired == false && bSkipUpdate == true))  // !(未过期 && 跳过更新)
	{
		if (Update::GetInstance()->CheckLocalVersion())
		{
			TRACEI(_T("igwInitialize DownloadUpdate"));

			if(!Update::GetInstance()->DownloadUpdate(pInfo->nAppID, pInfo->nAreaId, pInfo->nGroupId))
			{
				return SDOA_FALSE;
			}
		}
		else
		{
			TRACEI(_T("igwInitialize ForceUpdate"));

			if (!Update::GetInstance()->ForceUpdate(pInfo->nAppID, pInfo->nAreaId, pInfo->nGroupId))
			{
				return SDOA_FALSE;
			}
		}

	}
	
	GetModuleFileName(g_hModule, buffer, _countof(buffer));
#ifdef _WIN64
	sprintf(buffer + strlen(buffer) - strlen("sdologinentry64.dll"), "sdologin\\sdologinsdk64.dll");
#else
	sprintf(buffer + strlen(buffer) - strlen("sdologinentry.dll"), "sdologin\\sdologinsdk.dll");
#endif

	g_hSdoLogin = LoadLibraryEx(buffer, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
	//g_hSdoLogin = LoadLibrary(_T("sdologinsdk.dll"));

	LPigwInitialize pFun = (LPigwInitialize)GetProcAddress(g_hSdoLogin, "igwInitialize");
	if(pFun)
	{
		return pFun(dwSdkVersion, pAppInfo);
	}

	return SDOA_FALSE;
}
  • 这段代码是一个初始化函数 igwInitialize,通常作为某个 SDK 或模块的入口点。下面是对代码的详细解释:

    1. 首先,函数使用 GetEnvironmentVariable 获取当前环境变量中 PATH 的值,并将其存储在 path 变量中。然后,获取当前模块的文件路径,并将模块所在目录的路径添加到 path 变量中。

    2. 接着,检查许可证的过期状态和是否跳过更新。许可证管理器 LicenseManager 用于管理许可证信息。如果许可证未过期且未跳过更新,则执行更新操作。

    3. 如果本地版本需要更新,则调用 Update::GetInstance()->DownloadUpdate 方法进行更新下载。如果下载失败,则返回 SDOA_FALSE

    4. 如果本地版本无需更新,则调用 Update::GetInstance()->ForceUpdate 方法强制更新。如果更新失败,则返回 SDOA_FALSE

      • ForceUpdate代码定义:

      C++ 复制代码
      bool Update::ForceUpdate(int appId,int areaId,int groupId)
      {
      	TRACET();
      
      	OutputDebugStringW(L"ForceUpdate Enter");
      	m_AppId = appId;
      	m_AreaId = areaId;
      	m_GroupId = groupId;
      
      	bool ret = false;
      	CloseHandle(m_hProcessMutex);
      
      	static const size_t buff_size = 0x1000;
      	wchar_t buff[buff_size+1] = { 0 };
      #ifdef _DEBUG
      	swprintf(buff,L"ForceUpdate:[ProcessMutexName] %s",GetProcessMutexName());
      	OutputDebugStringW(buff);
      #endif
      
      	m_hProcessMutex = OpenMutex(MUTEX_ALL_ACCESS, TRUE, GetProcessMutexName());
      	if(m_hProcessMutex)
      	{
      		return ret;
      	}
      
      	HANDLE hUpdateMutex = OpenMutex(MUTEX_ALL_ACCESS, TRUE, GetUpdateMutexName());
      	if(hUpdateMutex)
      	{
      		return ret;
      	}
      
      	Update::GetInstance()->SendLogReport(112, "%d$$$%s$$$execmdline", GetLastError(), ::GetCommandLineA());
      
      	hUpdateMutex = CreateMutexA(NULL, TRUE, GetUpdateMutexName());
      
      	WCHAR path[MAX_PATH+32];
      	WCHAR tmppath[MAX_PATH+32];
      	GetModuleFileNameW(g_hModule, path, MAX_PATH);
      	GetModuleFileNameW(g_hModule, tmppath, MAX_PATH);
      	wcscat(path, L"/../");
      	wcscat(tmppath, L"/../temp");
      
      	//..
      	// 将宽字符字符串转换为 ANSI 字符串
      	//std::wstring strPath(path);
      	//std::wstring strTmpPath(tmppath);
      	//std::string bufferPath(strPath.begin(), strPath.end());
      	//std::string bufferTmpPath(strTmpPath.begin(), strTmpPath.end());
      	 使用 MessageBoxA 函数显示路径
      	//MessageBoxA(NULL, bufferPath.c_str(), "Path", MB_OK);
      	//MessageBoxA(NULL, bufferTmpPath.c_str(), "TmpPath", MB_OK);
      
      
      	int version = 1;
      	HANDLE handle = PtOpen(path, L"ver.bin", path, path);
      	if(handle)
      	{
      		PtVersionInfo info;
      		if(PtGetLatestVerInfo(handle, &info))
      		{
      			version = (int)info.verId;
      
      			// 将整数转换为字符串
      			//char buffer[256];
      			//sprintf(buffer, "Version: %d", version);
      
      			//MessageBoxA(NULL,buffer,"version提示",0);
      		}
      		PtClose(handle);
      	}
      	
      	TCHAR url[1024] = {0};
      	size_t size = _countof(url);
      
      	//,,,
      	// 打印 url、size 和 version 变量的值
      	//std::string msg = "url: " + std::string(url) + "\n"
      	//	+ "size: " + std::to_string(size) + "\n"
      	//	+ "version: " + std::to_string(version);
      
      	//MessageBoxA(NULL, msg.c_str(), "Variables", MB_OK);
      
      	// 打印 url、size 和 version 变量的值
      	//char buffer[1024];
      	//sprintf(buffer, "url: %s\nsize: %u\nversion: %d", url, size, version);
      
      	//MessageBoxA(NULL, buffer, "Variables", MB_OK);
      
      
      	Update::GetInstance()->GetUpdateUrl(url, size, version);
      #if 1
      	swprintf(buff,L"ForceUpdate:[UpdateUrl] %s",url);
      	OutputDebugStringW(buff);
      	
      	// 将 TCHAR 类型的字符串转换为 ANSI 字符串
      	//std::string strUrl(url);
      	//char bufferUrl[1024];
      	//strcpy_s(bufferUrl, strUrl.c_str());
      	 使用 MessageBoxA 函数显示 url
      	//MessageBoxA(NULL, bufferUrl, "UpdateUrl提示", MB_OK);
      #endif
      
      	wstring wurl = StringHelper::ANSIToUnicode(url);
      	handle = PtOpen(wurl.c_str(), L"ver.bin", path, tmppath);
      
      	// 将宽字符字符串转换为 ANSI 字符串
      	//std::string strWurl(wurl.begin(), wurl.end());
      	//const char* bufferWurl = strWurl.c_str();
      
      	 使用 MessageBoxA 函数显示 wurl
      	//MessageBoxA(NULL, bufferWurl, "UpdateUrl (Unicode)提示", MB_OK);
      
      	bool bRet = true;
      	if(handle)
      	{
      		TRACEI(_T("ForceUpdate UpdateFiles---------"));
      
      		CUpdateDlg dlg;
      		bRet = dlg.UpdateFiles(g_hModule, handle);
      
      		PtClose(handle);
      	}
      	ReleaseMutex(hUpdateMutex);
      	CloseHandle(hUpdateMutex);
      
      //  	ret = true;
      //  	if (bRet)
      //  	{
      //  		if (!SetupUpdate())
      //  		{
      //  			ret = false;
      //  		}
      //  	}
      //  	else
      //  	{
      //  		ret = false;
      //  	}
      #if 1
      	swprintf(buff,L"ForceUpdate:Finish");
      	OutputDebugStringW(buff);
      #endif
      	return bRet;
      }
      • 这段代码是 Update::ForceUpdate 方法的实现。一步步解释:

        1. 函数签名和日志输出:

          • 这个函数用于强制更新,传入三个参数:appIdareaIdgroupId
          • 函数开始时通过 OutputDebugStringW 输出调试日志,指示函数已经被调用。
        2. 初始化变量和互斥锁:

          • 初始化一些变量,包括 retbuffpathtmppath 等。
          • 调用 CloseHandle 关闭之前的进程互斥锁 m_hProcessMutex
          • 然后通过 OpenMutexCreateMutexA 创建新的进程互斥锁 m_hProcessMutexhUpdateMutex
        3. 获取当前模块路径和版本信息:

          • 使用 GetModuleFileNameW 获取当前模块的文件路径,分别存储在 pathtmppath 变量中。

            C++ 复制代码
            ---------------------------
            Path
            ---------------------------
            F:\ GL\Data\sdo2\sdologinentry.dll/../
            ---------------------------
            确定   
            ---------------------------
            
            
            ---------------------------
            TmpPath
            ---------------------------
            F:\ GL\Data\sdo2\sdologinentry.dll/../temp
            ---------------------------
            确定   
            ---------------------------
          • 根据路径拼接 ver.bin 文件的路径,调用 PtOpen 函数打开 ver.bin 文件,并获取其版本信息。

              C++ 复制代码
              ---------------------------
              version提示
              ---------------------------
              Version: 10903013
              ---------------------------
              确定   
              ---------------------------
        4. 获取更新地址:

          • 调用 Update::GetInstance()->GetUpdateUrl 方法获取更新地址,并将地址存储在 url 变量中。

            C++ 复制代码
            bool Update::GetUpdateUrl(TCHAR* url, size_t& size, int version)
            {
            	//MessageBoxA(NULL,"11","GetUpdateUrl提示",0);
            	
            
            
            	if(url == NULL || size < 1)
            	{
            		return false;
            	}
            	url[0] = 0;
            
            	TCHAR checkUrl[1024];
            	char checkValue[MD5LEN] = {0};
            	GetUpdateCheckValue(checkValue, version);
            	_stprintf(checkUrl, UPDATE_CHECK_URL, m_AppId, m_AreaId, m_GroupId, m_ClientSign, version, checkValue);
            
            	//....
            	// 将 TCHAR 类型的字符串转换为 ANSI 字符串
            	//std::string strCheckUrl(checkUrl);
            	//const char* bufferCheckUrl = strCheckUrl.c_str();
            	 使用 MessageBoxA 函数显示 checkUrl
            	//MessageBoxA(NULL, bufferCheckUrl, "CheckUrl提示GetUpdateUrl", MB_OK);
            
            
            	char data[1024];
            
            	memset(data, 0, sizeof(data));
            	size_t bufferSize = _countof(data);
            	if(GetUpdateServerUrl(checkUrl, data, bufferSize) && bufferSize > 0 && bufferSize < 1024)
            	{
            		data[bufferSize] = 0;
            		TiXmlDocument document;
            		document.Parse(data);
            		TiXmlElement* pElement = document.FirstChildElement(_T("verbinurl"));
            		if(pElement)
            		{
            			const char* value = pElement->GetText();
            			if(value)
            			{
            				_tcscpy(url, value);
            			}
            		}
            	}
            
            	if (strlen(url) < 1 || strcmp(url, "NULL") == 0)
            	{
            		SendLogReport(107, "%d$$$%s$$$Get Ver file url failed", GetLastError(), checkUrl);
            
            		_stprintf(url, UPDATE_URL, m_AppId);
            	}
            	return true;
            }
            • 这段代码是 Update::GetUpdateUrl 方法的实现。解释一下它的逻辑:

              1. 参数检查:

相关推荐
麻辣韭菜27 分钟前
网络基础 【HTTP】
网络·c++·http
阿史大杯茶40 分钟前
Codeforces Round 976 (Div. 2 ABCDE题)视频讲解
数据结构·c++·算法
转调1 小时前
每日一练:地下城游戏
开发语言·c++·算法·leetcode
wdxylb2 小时前
使用C++的OpenSSL 库实现 AES 加密和解密文件
开发语言·c++·算法
CSP126362 小时前
特别节目————集训总结
c++
程序猿阿伟2 小时前
《C++游戏人工智能开发:开启智能游戏新纪元》
c++·人工智能·游戏
N0zoM1z03 小时前
域内用户名枚举 实验
windows
一线青少年编程教师3 小时前
线性表三——队列queue
数据结构·c++·算法
C3 小时前
C++_智能指针详解
开发语言·c++
qinzechen3 小时前
分享几个做题网站------学习网------工具网;
java·c语言·c++·python·c#