typedef函数代码段解释以及部分Windows下的系统函数

这篇具有很好参考价值的文章主要介绍了typedef函数代码段解释以及部分Windows下的系统函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、typedef int (WINAPI* LPSDOLInitialize)(const SDOLAppInfo* pAppInfo)

C/C++ 中,typedef 用于创建类型别名,它可以让你为一个已有的数据类型定义一个新的名称,从而使代码更加清晰、易读,也可以简化类型的声明和使用。

这段代码用typedef定义了一个函数指针类型 LPSDOLInitialize,该函数指针指向一个函数,该函数接受一个指向 SDOLAppInfo 结构体的指针作为参数,并返回一个 int 类型的值。

具体来说,typedef 是用于创建类型别名的关键字。在这里,它创建了一个名为 LPSDOLInitialize 的新类型,它被定义为一个函数指针类型,该函数指针指向具有特定参数和返回类型的函数。

WINAPI 是一个宏,用于指定函数的调用约定,它在 Windows 平台上用于标识函数调用的方式和参数传递方式。

总结一下,该代码段定义了一个函数指针类型 LPSDOLInitialize,该指针可以指向一个具有特定参数和返回类型的函数,这个函数接受一个指向 SDOLAppInfo 结构体的指针作为参数,并返回一个 int 类型的值。这种函数指针的定义通常用于在运行时动态加载库中的函数并进行调用。

用这个函数指针类型 LPSDOLInitialize就可以创建对象: LLPSDOLInitialize m_pfSDOLInitialize;

例如,假设你想要声明一个函数指针变量来保存指向这样一个函数的指针,你可以这样写:

LPSDOLInitialize pFuncPointer;

这使得代码更加简洁,而不是每次都写完整的函数指针类型。typedef 在这里的作用就是为了创建一个新的名称,使代码更具可读性。

	//函数指针对象
	if (m_pfSDOLInitialize(&appinfo) != SDOL_ERRORCODE_OK)
	{
		return false;
	}

另外,typedef 还可以用于创建其他类型别名,如结构体、枚举等,以及用于更方便地处理复杂的数据类型。

2、typedef int (WINAPI* LPSDOLGetModule)(REFIID riid, void** intf)

这个 typedef 定义了另一个函数指针类型的别名 LPSDOLGetModule。这个函数指针指向一个具有以下特征的函数:

  • 返回类型为 int
  • 使用 WINAPI 调用约定。
  • 接受一个 REFIID 类型的参数 riid 和一个 void** 类型的参数 intf

3、typedef int (WINAPI* LPSDOLTerminal)();

这个 typedef 定义了第三个函数指针类型的别名 LPSDOLTerminal。这个函数指针指向一个具有以下特征的函数:

  • 返回类型为 int
  • 使用 WINAPI 调用约定。
  • 不接受任何参数。

为什么要使用 typedef 呢?使用 typedef 可以让代码更加清晰,提高可读性。通过定义这些函数指针类型的别名,可以更容易地声明和使用这些函数指针,特别是在涉及到多次使用相同函数指针类型的情况下。这有助于简化代码并提高可维护性。

4、GetProcAddress运行时获取一个动态链接库(DLL)中导出函数的地址

WINBASEAPI
FARPROC
WINAPI
GetProcAddress (
    __in HMODULE hModule,
    __in LPCSTR lpProcName
    );

这段代码片段是 Windows 操作系统的头文件和函数声明。让我为您解释一下这些概念:

  • WINBASEAPI: 这是一个宏,通常用于声明 Windows API 函数。它在 Windows 头文件中定义,并根据编译器和系统的不同进行设置。它的作用是为了确保在编译时使用正确的调用约定(calling convention)和导入/导出修饰符。

  • FARPROC: 这是一个函数指针类型,用于指向导入库函数。FARPROC 代表 “FAR Procedure”,在 32 位 Windows 中用于指向动态链接库(DLL)中的函数。

  • WINAPI: 这是一个宏,用于声明 Windows API 函数,同时指定函数的调用约定。WINAPI 宏的定义会根据编译器和系统的不同进行设置。通常,它会将函数调用约定设置为 __stdcall,这是一种用于 Windows API 的常见调用约定。

  • GetProcAddress: 这是 Windows API 中的一个函数,用于在运行时获取一个动态链接库(DLL)中导出函数的地址。这个函数在加载 DLL 后用于获取指定函数的指针,以便在程序中调用这些函数。

所以,这段代码片段声明了 GetProcAddress 函数,并提供了它的参数类型和说明。在实际代码中,您需要包含相关的 Windows 头文件,并根据需要使用这个函数来获取 DLL 中导出函数的指针,从而进行调用。

GetProcAddressWindows 操作系统提供的一个函数,用于在运行时获取一个动态链接库(DLL)中导出函数的地址。这个函数通常在动态链接库加载后被调用,用于获取库中特定函数的指针,以便在程序中调用这些函数。

函数签名如下:

FARPROC GetProcAddress(
  HMODULE hModule,    // 动态链接库的句柄
  LPCSTR  lpProcName   // 函数的名称或者是函数的序号
);
  • hModule: 指向已加载的动态链接库的句柄。通常使用 LoadLibrary 函数来加载动态链接库,然后将返回的句柄传递给 GetProcAddress

  • lpProcName: 要获取地址的函数的名称,或者是函数在导出表中的序号(函数的索引)。如果是名称,应该是一个以 NULL 结尾的字符串。

  • GetProcAddress 的返回值是一个函数指针,可以用于直接调用动态链接库中的函数。这对于动态加载库并在需要时使用其中的函数非常有用,特别是在插件式架构中或者需要在运行时决定调用哪些函数的情况下。

一个常见的用法是在加载插件时使用 GetProcAddress 来获取插件中的函数指针,然后通过这些指针来调用插件中的功能。

5、LoadLibraryExA 用于加载指定ANSI的动态链接库文件

WINBASEAPI
__out_opt
HMODULE
WINAPI
LoadLibraryExA(
    __in       LPCSTR lpLibFileName,
    __reserved HANDLE hFile,
    __in       DWORD dwFlags
    );

这段代码是 Windows API 函数 LoadLibraryExA 的声明。让我为您解释一下其中的参数和类型:

  • WINBASEAPI: 这是一个宏,用于声明 Windows API 函数。它在 Windows 头文件中定义,并根据编译器和系统的不同进行设置。

  • __out_opt: 这是一个标记,表示函数的返回值可以是一个可选的输出参数。在这个声明中,它表示函数的返回值 HMODULE 可能会被用作输出参数,以传递一个返回的模块句柄。

  • HMODULE: 这是一个 Windows 数据类型,表示模块(通常是 DLLEXE)的句柄。HMODULE 句柄是用于在程序中引用已加载模块的标识符。

  • WINAPI: 这是一个宏,用于声明 Windows API 函数,并指定函数的调用约定。通常情况下,它将函数调用约定设置为 __stdcall,这是一种用于 Windows API 的常见调用约定。

  • LoadLibraryExA: 这是一个 Windows API 函数,用于加载一个指定的动态链接库(DLL)文件。

  • lpLibFileName: 一个以 null 结尾的字符串,表示要加载的 DLL 文件名。LPCSTR 表示一个指向以 ANSI 字符集编码的字符串的指针。

  • hFile: 一个保留参数,传入 HANDLE 类型的文件句柄,或者传入 NULL

  • dwFlags: 一个标志,用于指定加载 DLL 的方式。可以是各种标志的组合,例如 :

    • DONT_RESOLVE_DLL_REFERENCES: 加载 DLL 但不解析其依赖项。
    • LOAD_LIBRARY_AS_DATAFILE: 将 DLL 视为数据文件而不是可执行文件。
    • LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: 仅在 DLL 所在的目录中搜索依赖项。

综合起来,这个声明表明了一个 Windows API 函数 LoadLibraryExA,它用于加载指定的动态链接库文件。函数返回一个 HMODULE 类型的句柄,表示已加载的模块。参数类型和标记都提供了函数使用和返回值的相关信息。

6、LoadLibraryExW 用于加载指定Wide宽字符的动态链接库文件

WINBASEAPI
__out_opt
HMODULE
WINAPI
LoadLibraryExW(
    __in       LPCWSTR lpLibFileName,
    __reserved HANDLE hFile,
    __in       DWORD dwFlags
    );

这段代码是 Windows API 函数 LoadLibraryExW 的声明。让我为您解释一下其中的参数和类型:

  • WINBASEAPI: 这是一个宏,用于声明 Windows API 函数。它在 Windows 头文件中定义,并根据编译器和系统的不同进行设置。

  • __out_opt: 这是一个标记,表示函数的返回值可以是一个可选的输出参数。在这个声明中,它表示函数的返回值 HMODULE 可能会被用作输出参数,以传递一个返回的模块句柄。

  • HMODULE: 这是一个 Windows 数据类型,表示模块(通常是 DLLEXE)的句柄。HMODULE 句柄是用于在程序中引用已加载模块的标识符。

  • WINAPI: 这是一个宏,用于声明 Windows API 函数,并指定函数的调用约定。通常情况下,它将函数调用约定设置为 __stdcall,这是一种用于 Windows API 的常见调用约定。

  • LoadLibraryExW: 这是一个 Windows API 函数,用于加载一个指定的动态链接库(DLL)文件。

  • lpLibFileName: 这是一个指向以 null 结尾的字符串的指针,表示要加载的动态链接库(DLL)的文件名。LPCWSTR 表示一个指向以宽字符(Unicode)编码的字符串的指针。您需要将要加载的 DLL 的文件名以宽字符格式传递给这个参数。

  • hFile: 一个保留参数,传入 HANDLE 类型的文件句柄,或者传入 NULL

  • dwFlags: 一个标志,用于指定加载 DLL 的方式。可以是各种标志的组合,例如 :

    • DONT_RESOLVE_DLL_REFERENCES: 加载 DLL 但不解析其依赖项。
    • LOAD_LIBRARY_AS_DATAFILE: 将 DLL 视为数据文件而不是可执行文件。
    • LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: 仅在 DLL 所在的目录中搜索依赖项。

综合起来,LoadLibraryExW 函数用于加载指定的 DLL 文件,并且通过参数来控制加载方式和行为。根据传递的文件名、文件句柄和标志,该函数将加载 DLL 并返回一个模块句柄(HMODULE),以便后续操作使用。不同之处在于该函数接受宽字符格式的文件名,适用于 Unicode 编码。

7、LoadLibraryA 用于加载指定ANSI的动态链接库文件

WINBASEAPI
__out_opt
HMODULE
WINAPI
LoadLibraryExA(
    __in       LPCSTR lpLibFileName,
    );

这段代码是 Windows API 函数 LoadLibraryA 的声明。让我为您解释一下其中的参数和类型:

  • WINBASEAPI: 这是一个宏,用于声明 Windows API 函数。它在 Windows 头文件中定义,并根据编译器和系统的不同进行设置。

  • __out_opt: 这是一个标记,表示函数的返回值可以是一个可选的输出参数。在这个声明中,它表示函数的返回值 HMODULE 可能会被用作输出参数,以传递一个返回的模块句柄。

  • HMODULE: 这是一个 Windows 数据类型,表示模块(通常是 DLLEXE)的句柄。HMODULE 句柄是用于在程序中引用已加载模块的标识符。

  • WINAPI: 这是一个宏,用于声明 Windows API 函数,并指定函数的调用约定。通常情况下,它将函数调用约定设置为 __stdcall,这是一种用于 Windows API 的常见调用约定。

  • LoadLibraryA: 这是一个 Windows API 函数,用于加载一个指定的动态链接库(DLL)文件。

  • lpLibFileName: 一个以 null 结尾的字符串,表示要加载的 DLL 文件名。LPCSTR 表示一个指向以 ANSI 字符集编码的字符串的指针。

综合起来,这个声明表明了一个 Windows API 函数 LoadLibraryA,它用于加载指定的动态链接库文件。函数返回一个 HMODULE 类型的句柄,表示已加载的模块。参数类型和标记都提供了函数使用和返回值的相关信息。总之,这个函数原型定义了 LoadLibraryA 函数的签名,它接受一个以多字节字符编码的 DLL 文件名作为参数,然后返回一个表示已加载模块的句柄。使用这个句柄,您可以执行与该模块相关的操作。

8、LoadLibraryW 用于加载指定Wide宽字符的动态链接库文件

WINBASEAPI
__out_opt
HMODULE
WINAPI
LoadLibraryExW(
    __in       LPCWSTR lpLibFileName,
    );

这段代码是 Windows API 函数 LoadLibraryW 的声明。让我为您解释一下其中的参数和类型:

  • WINBASEAPI: 这是一个宏,用于声明 Windows API 函数。它在 Windows 头文件中定义,并根据编译器和系统的不同进行设置。

  • __out_opt: 这是一个标记,表示函数的返回值可以是一个可选的输出参数。在这个声明中,它表示函数的返回值 HMODULE 可能会被用作输出参数,以传递一个返回的模块句柄。

  • HMODULE: 这是一个 Windows 数据类型,表示模块(通常是 DLLEXE)的句柄。HMODULE 句柄是用于在程序中引用已加载模块的标识符。

  • WINAPI: 这是一个宏,用于声明 Windows API 函数,并指定函数的调用约定。通常情况下,它将函数调用约定设置为 __stdcall,这是一种用于 Windows API 的常见调用约定。

  • LoadLibraryW: 这是一个 Windows API 函数,用于加载一个指定的动态链接库(DLL)文件。

  • lpLibFileName: 这是一个指向以 null 结尾的字符串的指针,表示要加载的动态链接库(DLL)的文件名。LPCWSTR 表示一个指向以宽字符(Unicode)编码的字符串的指针。您需要将要加载的 DLL 的文件名以宽字符格式传递给这个参数。

综合起来,LoadLibraryW 函数用于加载指定的 DLL 文件。根据传递的文件名、文件句柄和标志,该函数将加载 DLL 并返回一个模块句柄(HMODULE),以便后续操作使用。不同之处在于该函数接受宽字符格式的文件名,适用于 Unicode 编码。总之,这个函数原型定义了 LoadLibraryA 函数的签名,它接受一个以Unicode编码的 DLL 文件名作为参数,然后返回一个表示已加载模块的句柄。使用这个句柄,您可以执行与该模块相关的操作。

9、LoadLibraryExA和LoadLibraryA以及LoadLibraryExW和LoadLibraryW区别

这些函数是 Windows API 中用于加载动态链接库 (DLL) 的函数,主要区别在于它们支持的字符串类型和加载选项:

  • LoadLibraryExALoadLibraryA
    • LoadLibraryExA:用于以 ANSI 编码加载 DLL。它接受 ANSI 字符串作为参数。
    • LoadLibraryA:也用于以 ANSI 编码加载 DLL。与 LoadLibraryExA 类似,但没有额外的加载选项。

这两个函数的主要区别在于 LoadLibraryExA 支持额外的加载选项,如指定加载行为和加载上下文等。而 LoadLibraryA 是基本的加载函数,不提供这些选项。

  • LoadLibraryExWLoadLibraryW
    • LoadLibraryExW:用于以 Unicode 编码加载 DLL。它接受 Unicode 字符串作为参数。
    • LoadLibraryW:也用于以 Unicode 编码加载 DLL。与 LoadLibraryExW 类似,但没有额外的加载选项。

这两个函数的区别与前面所述的 ANSI 版本类似,LoadLibraryExW 支持额外的加载选项,而 LoadLibraryW 是基本的加载函数。

在选择使用哪个函数时,您需要根据字符串的编码和加载选项来决定。如果您使用的是 ANSI 字符串,可以选择 LoadLibraryExA 或 LoadLibraryA。如果您使用的是 Unicode 字符串,可以选择 LoadLibraryExWLoadLibraryW。如果您需要额外的加载选项,可以使用以 “Ex” 结尾的版本。

10、typedef函数声明与实现的例子

10.1、函数定义

typedef int (WINAPI* LPSDOLInitialize)(const SDOLAppInfo* pAppInfo);
typedef int (WINAPI* LPSDOLGetModule)(REFIID riid, void** intf);
typedef int (WINAPI* LPSDOLTerminal)();

10.2、函数实现加载动态链接库

bool Initial(){	
	WCHAR strExePath[MAX_PATH] = { 0 };
	WCHAR strExeName[MAX_PATH] = { 0 };
	WCHAR* strLastSlash = NULL;
	GetModuleFileNameW(NULL, strExePath, MAX_PATH);
	strExePath[MAX_PATH - 1] = 0;
	strLastSlash = wcsrchr(strExePath, TEXT('\\'));
	if (strLastSlash)
	{	// 得到EXE所在路径
		StringCchCopyW(strExeName, MAX_PATH, &strLastSlash[1]);
		*strLastSlash = 0;
		strLastSlash = wcsrchr(strExeName, TEXT('.'));
		if (strLastSlash)
			*strLastSlash = 0;
	}

	WCHAR strGameWidgetDll[MAX_PATH] = { 0 };
#ifdef _WIN64
	StringCchPrintfW(strGameWidgetDll, MAX_PATH, L"%s\\sdo\\sdologinentry64.dll", strExePath);
#else
	StringCchPrintfW(strGameWidgetDll, MAX_PATH, L"%s\\sdo\\sdologinentry.dll", strExePath);
#endif
	if (GetFileAttributesW(strGameWidgetDll) == 0xFFFFFFFF) {
		return false;
	}
//	string strEntry;
//#ifdef _WIN64
//	strEntry = PathHelper::GetFullPath("..\\sdologinentry64.dll");
//#else
//	strEntry = PathHelper::GetFullPath("..\\sdologinentry.dll");
//#endif
    m_hSDOLoginModule = ::LoadLibraryW(strGameWidgetDll);
	if (m_hSDOLoginModule == nullptr)
	{
		return false;
	}
	
	//Out-of-game login interface
	m_pfSDOLInitialize = (LPSDOLInitialize)GetProcAddress(m_hSDOLoginModule, "SDOLInitialize");
	m_pfSDOLGetModule = (LPSDOLGetModule)GetProcAddress(m_hSDOLoginModule, "SDOLGetModule");
	m_pfSDOLTerminal = (LPSDOLTerminal)GetProcAddress(m_hSDOLoginModule, "SDOLTerminal");

	if (m_pfSDOLInitialize == nullptr || m_pfSDOLGetModule == nullptr) return false;
}
  WCHAR strExePath[MAX_PATH] = { 0 };

WCHAR strExeName[MAX_PATH] = { 0 };
WCHAR* strLastSlash = NULL;
GetModuleFileNameW(NULL, strExePath, MAX_PATH);
strExePath[MAX_PATH - 1] = 0;
strLastSlash = wcsrchr(strExePath, TEXT(‘\’));
if (strLastSlash)
{ // 得到EXE所在路径
StringCchCopyW(strExeName, MAX_PATH, &strLastSlash[1]);
*strLastSlash = 0;
strLastSlash = wcsrchr(strExeName, TEXT(‘.’));
if (strLastSlash)
*strLastSlash = 0;
}

	WCHAR strGameWidgetDll[MAX_PATH] = { 0 };
	#ifdef _WIN64
		StringCchPrintfW(strGameWidgetDll, MAX_PATH, L"%s\\sdo\\sdologinentry64.dll", strExePath);
	#else
		StringCchPrintfW(strGameWidgetDll, MAX_PATH, L"%s\\sdo\\sdologinentry.dll", strExePath);
	#endif
		if (GetFileAttributesW(strGameWidgetDll) == 0xFFFFFFFF) {
			return false;
		}
	//	string strEntry;
	//#ifdef _WIN64
	//	strEntry = PathHelper::GetFullPath("..\\sdologinentry64.dll");
	//#else
	//	strEntry = PathHelper::GetFullPath("..\\sdologinentry.dll");
	//#endif
    m_hSDOLoginModule = ::LoadLibraryW(strGameWidgetDll);
	if (m_hSDOLoginModule == nullptr)
	{
		return false;
	}

代码解释:

  • 获取当前执行程序的路径和名称:
    • 使用 GetModuleFileNameW 函数获取当前执行程序**(.exe)**的路径,并将其存储在 strExePath 中。
    • strExePath 中提取出执行程序的名称并存储在 strExeName 中。
  • 提取执行程序所在目录:
    • strExePath 中找到最后一个反斜杠 “” 的位置,然后将它替换为 NULL 终止字符以分隔目录路径和文件名。
    • 如果存在文件扩展名,也将其删除,以便获得纯粹的目录路径。
  • 根据当前架构构造 strGameWidgetDll 的路径:
    • 根据操作系统架构(32位或64位),构建 strGameWidgetDll 路径,这是一个包含了 “sdologinentry.dll” 或 “sdologinentry64.dll” 的完整路径。
  • 检查文件是否存在:
    • 使用 GetFileAttributesW 函数检查 strGameWidgetDll 文件是否存在,如果文件不存在,就返回 false
  • 加载动态链接库(DLL):
    • 使用 LoadLibraryW 函数加载 strGameWidgetDll 指定的 DLL 文件。如果加载失败,返回 false

这段代码的目的是获取并加载一个特定的 DLL,该 DLL 位于与当前执行程序相同的目录下,根据操作系统架构选择加载 “sdologinentry.dll” 或 “sdologinentry64.dll”。如果加载成功,m_hSDOLoginModule 将包含该 DLL 的句柄,以便后续可以使用 GetProcAddress 来获取其中的函数地址。如果有任何错误发生,函数将返回 false

m_pfSDOLInitialize = (LPSDOLInitialize)GetProcAddress(m_hSDOLoginModule, “SDOLInitialize”);

代码解释:

  • m_pfSDOLInitialize 是一个函数指针,它似乎被用来指向一个函数,该函数的名称是 “SDOLInitialize”,并且这个函数是从模块 m_hSDOLoginModule 中获取的。这种情况通常用于动态链接库(Dynamic Link Library,DLL)或共享库中的函数调用。
  • 一般来说,这段代码的目的是将 m_pfSDOLInitialize 这个函数指针指向 m_hSDOLoginModule 模块中的 “SDOLInitialize” 函数,而m_hSDOLoginModule 模块是一个动态链接库中函数调用,以便后续可以通过该函数指针来调用 “SDOLInitialize” 函数,而不必直接链接到该函数的库。这种方式通常用于在运行时加载库并调用其中的函数,而不是在编译时链接到库。
  • 在使用 m_pfSDOLInitialize 这个函数指针之前,你需要确保 m_hSDOLoginModule 已经成功加载,并且 “SDOLInitialize” 函数已经在该模块中找到。否则,使用该函数指针可能导致运行时错误。

m_pfSDOLGetModule = (LPSDOLGetModule)GetProcAddress(m_hSDOLoginModule, “SDOLGetModule”);

代码解释:

  • 定义了一个函数指针 m_pfSDOLGetModule,并使用 GetProcAddress 函数从 m_hSDOLoginModule 模块中获取 “SDOLGetModule” 函数的地址,并将其分配给 m_pfSDOLGetModule。这意味着 m_pfSDOLGetModule 现在指向了 m_hSDOLoginModule 中的 “SDOLGetModule” 函数。
  • 这种操作通常用于动态加载函数,使你能够在运行时调用这些函数,而无需在编译时将其链接到代码中。 在使用 m_pfSDOLGetModule 指向的函数之前,你需要确保 m_hSDOLoginModule 已成功加载,并且 “SDOLGetModule” 函数确实存在于该模块中,否则会导致运行时错误。

m_pfSDOLTerminal = (LPSDOLTerminal)GetProcAddress(m_hSDOLoginModule, “SDOLTerminal”);

代码解释:文章来源地址https://www.toymoban.com/news/detail-653963.html

  • 定义了一个函数指针 m_pfSDOLTerminal,并使用 GetProcAddress 函数从 m_hSDOLoginModule 模块中获取 “SDOLTerminal” 函数的地址,并将其分配给 m_pfSDOLTerminal。这样,m_pfSDOLTerminal 现在指向了 m_hSDOLoginModule 中的 “SDOLTerminal” 函数。
  • 这种操作允许你在运行时动态加载并调用 “SDOLTerminal” 函数,而无需在编译时将其链接到代码中。 在使用 m_pfSDOLTerminal 指向的函数之前,确保 m_hSDOLoginModule 已成功加载,且 “SDOLTerminal” 函数确实存在于该模块中,以避免运行时错误。这样的方式通常用于插件系统或需要在运行时加载不同模块的应用程序。

if (m_pfSDOLInitialize == nullptr || m_pfSDOLGetModule == nullptr) return false;

代码解释:

  • 代码检查了 m_pfSDOLInitializem_pfSDOLGetModule 这两个函数指针是否为空指针(nullptr)。如果其中任何一个为空,它返回 false,否则继续执行后续的操作。
  • 这种检查通常用于确保成功加载并获取到所需的函数地址。如果在前面的 GetProcAddress 调用中,未能获取到 “SDOLInitialize” 或 “SDOLGetModule” 函数的地址,这些函数指针将会是空指针。因此,通过检查它们是否为空,你可以在继续使用这些函数指针之前确保它们已成功获取,以避免在尝试调用这些函数时引发未定义行为或错误。
  • 这是一种常见的做法,用于提高代码的鲁棒性,特别是在涉及动态加载函数的情况下。如果函数指针不为空,那么它们将指向有效的函数,否则你可以选择采取适当的错误处理措施。

10.3、sdologinentry.dll或者sdologinentry64.dll动态链接库哪个工程生成的并导出三个接口函数

很明显由updatecore工程生成的sdologinentry.dllsdologinentry64.dll的动态链接库。

typedef函数代码段解释以及部分Windows下的系统函数,c,C++,c++

int WINAPI SDOLInitialize(const SDOLAppInfo* pAppInfo)
{
	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);

	SDOLAppInfo* pInfo = (SDOLAppInfo*)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())
		{
			if(!Update::GetInstance()->DownloadUpdate(pInfo->AppID, pInfo->AreaId, pInfo->GroupId))
			{
				return SDOA_FALSE;
			}
		}
		else
		{
			if (!Update::GetInstance()->ForceUpdate(pInfo->AppID, pInfo->AreaId, pInfo->GroupId))
			{
				return SDOA_FALSE;
			}
		}
	}

/*
#ifdef _WIN64
	g_hSdoLogin = LoadLibrary(_T("sdologinsdk64.dll"));
#else
	g_hSdoLogin = LoadLibrary(_T("sdologinsdk.dll"));
#endif
*/

	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);

	LPSDOLInitialize pFun = (LPSDOLInitialize)GetProcAddress(g_hSdoLogin, "SDOLInitialize");
	if(pFun)
	{
		return pFun(pAppInfo);
	}
	return SDOA_FALSE;
}

int WINAPI SDOLGetModule(REFIID riid, void** intf)
{
	LPSDOLGetModule pFun = (LPSDOLGetModule)GetProcAddress(g_hSdoLogin, "SDOLGetModule");
	if(pFun)
	{
		return pFun(riid, intf);
	}
	return false;
}

int WINAPI SDOLTerminal()
{
	LPSDOLTerminal pFun = (LPSDOLTerminal)GetProcAddress(g_hSdoLogin, "SDOLTerminal");
	int ret = SDOA_FALSE;
	if(pFun)
	{
		ret = pFun();
	}

	FreeLibrary(g_hSdoLogin);

	if(ret == SDOL_ERRORCODE_OK)
	{
		Update::GetInstance()->SetupUpdate();
	}
	Update::Destroy();

	return ret;
}

int WINAPI SDOLInitialize(const SDOLAppInfo* pAppInfo)

{

​ 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);

​ SDOLAppInfo* pInfo = (SDOLAppInfo*)pAppInfo;

​ SetEnvironmentVariable(_T(“PATH”), path);

​ SDOLAppInfo* pInfo = (SDOLAppInfo*)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(“Expiration”);
​ bool bSkipUpdate = LicenseManager::GetInstance()->GetValue(“SkipUpdate”);

​ if (!(bExpired == false && bSkipUpdate == true)) // !(未过期 && 跳过更新)
​ {
​ if (Update::GetInstance()->CheckLocalVersion())
​ {
​ if(!Update::GetInstance()->DownloadUpdate(pInfo->AppID, pInfo->AreaId, pInfo->GroupId))
​ {
​ return SDOA_FALSE;
​ }
​ }
​ else
​ {
​ if (!Update::GetInstance()->ForceUpdate(pInfo->AppID, pInfo->AreaId, pInfo->GroupId))
​ {
​ return SDOA_FALSE;
​ }
​ }
​ }

/*
#ifdef _WIN64
g_hSdoLogin = LoadLibrary(_T(“sdologinsdk64.dll”));
#else
g_hSdoLogin = LoadLibrary(_T(“sdologinsdk.dll”));
#endif
*/

​ 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);

​ LPSDOLInitialize pFun = (LPSDOLInitialize)GetProcAddress(g_hSdoLogin, “SDOLInitialize”);
​ if(pFun)
​ {
​ return pFun(pAppInfo);
​ }
​ return SDOA_FALSE;

}

代码解释:

  • 这段代码是一个函数 SDOLInitialize 的实现,以下是它的主要功能:
    1. 获取当前环境变量中的 PATH,并向其中添加一个目录路径。这个目录路径是 sdologin 目录,它相对于当前执行程序的目录。
    2. 初始化 LicenseManager,它的目的是获取和检查许可证信息。
    3. 检查许可证信息中的 “Expiration” 和 “SkipUpdate” 值,根据这些值决定是否跳过更新过程。
    4. 如果不跳过更新,检查本地版本并尝试下载或强制更新。
    5. 最后,通过构建动态链接库文件路径,加载 sdologinsdk.dllsdologinsdk64.dll(取决于系统架构),同理并调用动态链接库中的 SDOLInitialize 函数。
  • 总体来说,这段代码的功能是在初始化时检查许可证信息,决定是否需要进行更新,并加载相应的动态链接库以继续应用程序的初始化过程。根据许可证信息,它可能跳过更新或执行更新操作。这种方式通常用于软件的自动更新或版本管理。

int WINAPI SDOLGetModule(REFIID riid, void** intf)
{
LPSDOLGetModule pFun = (LPSDOLGetModule)GetProcAddress(g_hSdoLogin, “SDOLGetModule”);
if(pFun)
{
return pFun(riid, intf);
}
return false;
}

代码解释:

  • 这段代码是一个函数 SDOLGetModule 的实现,以下是它的主要功能:
    1. 首先,它通过 GetProcAddress 函数尝试从同理并调用动态链接库中的加载的 g_hSdoLogin 动态链接库中获取名为 “SDOLGetModule” 的函数的地址,这个函数似乎是一个用于获取模块的接口(COM 接口)的函数。
    2. 如果成功获取到该函数的地址,它调用该函数,并将 riidintf 参数传递给它。
    3. 如果获取和调用都成功,函数返回从 pFun 调用的结果。
    4. 如果无法获取到该函数的地址,或者获取和调用失败,函数返回 false
  • 这段代码似乎是为了实现动态加载的模块系统,其中 SDOLGetModule 函数用于获取指定接口的模块。如果成功获取到并调用了模块中的 SDOLGetModule 函数,它将返回相应的结果,否则返回 false 表示失败。通常,这种方式用于插件系统或模块化的应用程序,可以在运行时加载不同的模块并获取它们的接口。

int WINAPI SDOLTerminal()
{
LPSDOLTerminal pFun = (LPSDOLTerminal)GetProcAddress(g_hSdoLogin, “SDOLTerminal”);
int ret = SDOA_FALSE;
if(pFun)
{
ret = pFun();
}

​ FreeLibrary(g_hSdoLogin);

​ if(ret == SDOL_ERRORCODE_OK)
​ {
​ Update::GetInstance()->SetupUpdate();
​ }
​ Update::Destroy();

​ return ret;

}

代码解释:

  • 这段代码是一个函数 SDOLTerminal 的实现,以下是它的主要功能:

    1. 首先,它通过 GetProcAddress 函数尝试从同理并调用动态链接库中的加载的 g_hSdoLogin 动态链接库中获取名为 “SDOLTerminal” 的函数的地址,似乎是一个用于终止模块操作的函数。
    2. 如果成功获取到该函数的地址,它调用该函数,并将返回的结果存储在 ret 变量中。
    3. 接着,它使用 FreeLibrary 函数释放 g_hSdoLogin 动态链接库,即卸载模块。
    4. 如果 ret 的值等于 SDOL_ERRORCODE_OK,则表示成功执行模块操作,它会调用 Update::GetInstance()->SetupUpdate() 来设置更新,否则跳过这一步。
    5. 最后,它调用 Update::Destroy() 来释放更新相关的资源,并返回 ret 的值。
  • 这段代码的主要作用是在模块操作结束时,执行一些清理工作,包括释放动态链接库,进行更新设置,以及资源的销毁。这通常用于模块的初始化和终止过程。

解释如何调用到sdologinentry.dll或者sdologinentry64.dll库中的三个函数:

SDOLInitialize

SDOLGetModule

SDOLTerminal

LIBRARY	"updatecore"

EXPORTS
	igwInitialize
	igwGetModule
	igwTerminal
	SDOLInitialize
	SDOLGetModule
	SDOLTerminal

资源解释:

  • 这是一个动态链接库(DLL)的导出符号定义部分。在这个定义中:
    • LIBRARY "updatecore" 表示该动态链接库的名称为 “updatecore”。
    • EXPORTS 下面列出了一系列函数名称,它们将会在该 DLL 中被导出,以便其他模块或程序可以调用这些函数。这些函数包括了 igwInitializeigwGetModuleigwTerminalSDOLInitializeSDOLGetModule 以及 SDOLTerminal
  • 这些导出函数通常是其他程序或模块需要使用的接口。通过将它们导出,其他程序可以通过动态链接的方式加载这个 DLL,并使用这些函数来执行特定的操作。在你之前提供的代码中,通过 GetProcAddress 函数来获取并调用这些函数,这使得你可以在运行时动态加载和使用这些功能。

10.4、sdologinsdk.dll或者sdologinsdk64.dll动态链接库哪个工程生成并导出三个接口函数

SDOLInitialize

SDOLGetModule

SDOLTerminal

很明显由sdk工程生成的sdologinsdk.dllsdologinsdk64.dll的动态链接库。

typedef函数代码段解释以及部分Windows下的系统函数,c,C++,c++

static SDOLLogin* g_pSDOLLogin = NULL;
static SDOLInfo*  g_pSDOLInfo = NULL;
bool _SDOLGetModule(REFIID riid, void** intf);
bool _igwGetModule(REFIID riid, void** intf);

int WINAPI SDOLInitializeInternal(const SDOLAppInfo* pAppInfo)
{
	TRACET();
	TRACEI(_T("pAppInfo[0x%x]\n"), pAppInfo);

	if(pAppInfo == NULL || pAppInfo->Size != sizeof(SDOLAppInfo))
	{
		TRACEW("SDOLII pAppInfo error.");
		return SDOL_ERRORCODE_INVALIDPARAM;
	}

	if(!ModuleLoginSDK::Initial(pAppInfo))
	{
		TRACEW("ModuleLoginSDK::Initial() failed.");
		return SDOL_ERRORCODE_FAILED;
	}

	TRACEI(_T("AppID[%d] AppName[%s] AppVer[%s] AreaId[%d] GroupId[%d]\n"), 
		pAppInfo->AppID, pAppInfo->AppName, pAppInfo->AppVer, pAppInfo->AreaId, pAppInfo->GroupId);

	//ModuleLoginSDK::GetInstance()->SetAppInfo(pAppInfo);

	g_pSDOLLogin = new SDOLLogin();
	g_pSDOLInfo = new SDOLInfo();

	return SDOL_ERRORCODE_OK;
};


bool _InitObjects( const SDOLAppInfo& appInfo ) ;
int WINAPI SDOLInitialize(const SDOLAppInfo* pAppInfo)
{
	TRACET();
	TRACEI(_T("pAppInfo[0x%x]\n"), pAppInfo);
	if (NULL != pAppInfo)
	{
		TRACEI(_T("pAppInfo->Size[%d]\n"), pAppInfo->Size);
		TRACEI(_T("pAppInfo->AppID[%d]\n"), pAppInfo->AppID);
		TRACEI(_T("pAppInfo->AppName[%s]\n"), pAppInfo->AppName);
		TRACEI(_T("pAppInfo->AppVer[%s]\n"), pAppInfo->AppVer);
		TRACEI(_T("pAppInfo->AreaId[%d]\n"), pAppInfo->AreaId);
	}

	// zlc bool res = _InitObjects(*pAppInfo);
	SDOLAppInfo struAppInfo;
	memcpy(&struAppInfo, pAppInfo, sizeof(SDOLAppInfo));
	if (struAppInfo.AppID == 0)
		struAppInfo.AppID = 791000388; //zlc here
	bool res = _InitObjects(struAppInfo);
	if (!res)
	{
		return SDOL_ERRORCODE_FAILED;
	}

	ModuleLoginSDK::GetInstance()->SetWindowMode(SetWindowModeReq::OutsideGame);

	return SDOL_ERRORCODE_OK;
};



int WINAPI SDOLGetModule(REFIID riid, void** intf)
{
	TRACET();

	OLECHAR* guid = NULL; 
	StringFromIID(riid, &guid);
	TRACEI(_T("0 SDOLGetModule riid[%s]"), guid);

	bool res = false;
	res = _SDOLGetModule(riid, intf);
	if (!res)
	{
		res = _igwGetModule(riid, intf);
	}

	if (res)
	{
		OLECHAR* guid = NULL; 
		StringFromIID(riid, &guid);
		TRACEI(_T("1 SDOLGetModule riid[%s]"), guid);
	}	

	return res ? SDOL_ERRORCODE_OK:SDOL_ERRORCODE_FAILED;
};

int WINAPI SDOLTerminal()
{
	TRACET();
	TRACEI(_T(""));

	int ret = ModuleLoginSDK::Destroy();

	SAFE_DELETE(g_pSDOLLogin);

	return ret == ShutdownSuccess ? SDOL_ERRORCODE_OK : SDOL_ERRORCODE_FAILED;
};

bool _SDOLGetModule(REFIID riid, void** intf)
{
	TRACET();
	TRACEI(_T(""));

	if(riid == __uuidof(ISDOLLogin))
	{
		*intf = (void*)(ISDOLLogin*)g_pSDOLLogin;
		return true;
	}
	if(riid == __uuidof(ISDOLLogin2))
	{
		*intf = (void*)(ISDOLLogin2*)g_pSDOLLogin;
		return true;
	}
	if (riid == __uuidof(ISDOLInfo))
	{
		*intf = (void*)(ISDOLInfo*)g_pSDOLInfo;
		return true;
	}
	if(riid == __uuidof(ISDOLLogin3))
	{
		*intf = (void*)(ISDOLLogin3*)g_pSDOLLogin;
		return true;
	}
	if(riid == __uuidof(ISDOLLogin4))
	{
		*intf = (void*)(ISDOLLogin4*)g_pSDOLLogin;
		return true;
	}
	if(riid == __uuidof(ISDOLLogin5))
	{
		*intf = (void*)(ISDOLLogin5*)g_pSDOLLogin;
		return true;
	}
	if(riid == __uuidof(ISDOLLogin6))
	{
		*intf = (void*)(ISDOLLogin6*)g_pSDOLLogin;
		return true;
	}
	if(riid == __uuidof(ISDOLLogin7))
	{
		*intf = (void*)(ISDOLLogin7*)g_pSDOLLogin;
		return true;
	}
	if(riid == __uuidof(ISDOLLogin8))
	{
		*intf = (void*)(ISDOLLogin8*)g_pSDOLLogin;
		return true;
	}

	return false;
};

static SDOLLogin* g_pSDOLLogin = NULL;
static SDOLInfo* g_pSDOLInfo = NULL;
bool _SDOLGetModule(REFIID riid, void** intf);
bool _igwGetModule(REFIID riid, void** intf);

int WINAPI SDOLInitializeInternal(const SDOLAppInfo* pAppInfo)
{
TRACET();
TRACEI(_T(“pAppInfo[0x%x]\n”), pAppInfo);

​ if(pAppInfo == NULL || pAppInfo->Size != sizeof(SDOLAppInfo))
​ {
​ TRACEW(“SDOLII pAppInfo error.”);
​ return SDOL_ERRORCODE_INVALIDPARAM;
​ }

​ if(!ModuleLoginSDK::Initial(pAppInfo))
​ {
​ TRACEW(“ModuleLoginSDK::Initial() failed.”);
​ return SDOL_ERRORCODE_FAILED;
​ }

​ TRACEI(_T(“AppID[%d] AppName[%s] AppVer[%s] AreaId[%d] GroupId[%d]\n”),
​ pAppInfo->AppID, pAppInfo->AppName, pAppInfo->AppVer, pAppInfo->AreaId, pAppInfo->GroupId);

​ //ModuleLoginSDK::GetInstance()->SetAppInfo(pAppInfo);

​ g_pSDOLLogin = new SDOLLogin();
​ g_pSDOLInfo = new SDOLInfo();

​ return SDOL_ERRORCODE_OK;

};

代码解释:

  • 这段代码定义了一个名为 SDOLInitializeInternal 的函数,以下是它的主要功能:

    1. 在函数开始时,通过 TRACEI 函数和 TRACEW 函数输出一些信息,用于调试和日志记录。
    2. 首先,它检查传入的 pAppInfo 参数是否为 NULL 或其大小是否与 sizeof(SDOLAppInfo) 相符。如果不符合条件,函数会返回 SDOL_ERRORCODE_INVALIDPARAM 表示参数无效。
    3. 接着,如果上述检查通过,它调用 ModuleLoginSDK::Initial(pAppInfo) 函数,尝试进行一些初始化操作。如果初始化失败,函数返回 SDOL_ERRORCODE_FAILED 表示初始化失败。
    4. 如果初始化成功,它继续输出 pAppInfo 中的一些信息,包括了 AppIDAppNameAppVerAreaIdGroupId
    5. 然后,它创建了两个对象:g_pSDOLLoging_pSDOLInfo,分别是 SDOLLoginSDOLInfo 的实例。
    6. 最后,函数返回 SDOL_ERRORCODE_OK 表示初始化成功。
  • 这段代码的主要目的是在应用程序的初始化过程中,根据传入的应用信息进行一些初始化工作,包括了调用 ModuleLoginSDK::Initial 函数,创建 SDOLLoginSDOLInfo 的对象。如果初始化成功,函数返回成功状态码,否则返回失败状态码。

bool _InitObjects( const SDOLAppInfo& appInfo ) ;
int WINAPI SDOLInitialize(const SDOLAppInfo* pAppInfo)
{
TRACET();
TRACEI(_T(“pAppInfo[0x%x]\n”), pAppInfo);
if (NULL != pAppInfo)
{
TRACEI(_T(“pAppInfo->Size[%d]\n”), pAppInfo->Size);
TRACEI(_T(“pAppInfo->AppID[%d]\n”), pAppInfo->AppID);
TRACEI(_T(“pAppInfo->AppName[%s]\n”), pAppInfo->AppName);
TRACEI(_T(“pAppInfo->AppVer[%s]\n”), pAppInfo->AppVer);
TRACEI(_T(“pAppInfo->AreaId[%d]\n”), pAppInfo->AreaId);
}

​ // zlc bool res = _InitObjects(*pAppInfo);
​ SDOLAppInfo struAppInfo;
​ memcpy(&struAppInfo, pAppInfo, sizeof(SDOLAppInfo));
​ if (struAppInfo.AppID == 0)
​ struAppInfo.AppID = 791000388; //zlc here
​ bool res = _InitObjects(struAppInfo);
​ if (!res)
​ {
​ return SDOL_ERRORCODE_FAILED;
​ }

​ ModuleLoginSDK::GetInstance()->SetWindowMode(SetWindowModeReq::OutsideGame);

​ return SDOL_ERRORCODE_OK;

};

代码解释:

  • 这段代码是一个名为 SDOLInitialize 的函数的实现,以下是它的主要功能:

    1. 在函数开始时,通过一系列 TRACEI 函数调用来输出一些信息,这些信息包括了 pAppInfo 参数的各个成员的值,以便进行调试和日志记录。
    2. 接着,它创建一个名为 struAppInfo 的局部变量,并通过 memcpy 函数将 pAppInfo 的内容复制到 struAppInfo 中。然后,它检查 struAppInfo 中的 AppID 是否为 0,如果是,将其设置为 791000388。
    3. 接下来,它调用 _InitObjects 函数,将 struAppInfo 作为参数传递给它。_InitObjects 函数可能用于初始化一些对象或资源,这部分的具体逻辑在 _InitObjects 函数中实现。
    4. 如果 _InitObjects 返回 true 表示初始化成功,它将调用 ModuleLoginSDK::GetInstance()->SetWindowMode(SetWindowModeReq::OutsideGame) 来设置某种窗口模式。窗口模式的设置可能与应用程序的显示方式有关。
    5. 最后,如果初始化成功,函数返回 SDOL_ERRORCODE_OK,否则返回 SDOL_ERRORCODE_FAILED 表示初始化失败。
  • 总的来说,这段代码的目的是在应用程序初始化过程中,根据传入的应用信息进行一些初始化工作,包括了调用 _InitObjects 函数和设置窗口模式。如果初始化成功,返回成功状态码,否则返回失败状态码。

int WINAPI SDOLGetModule(REFIID riid, void** intf)
{
TRACET();

​ OLECHAR* guid = NULL;
​ StringFromIID(riid, &guid);
​ TRACEI(_T(“0 SDOLGetModule riid[%s]”), guid);

​ bool res = false;
​ res = _SDOLGetModule(riid, intf);
​ if (!res)
​ {
​ res = _igwGetModule(riid, intf);
​ }

​ if (res)
​ {
​ OLECHAR* guid = NULL;
​ StringFromIID(riid, &guid);
​ TRACEI(_T(“1 SDOLGetModule riid[%s]”), guid);
​ }

​ return res ? SDOL_ERRORCODE_OK:SDOL_ERRORCODE_FAILED;

};

代码解释:

  • 这段代码是一个名为 SDOLGetModule 的函数的实现,以下是它的主要功能:
    1. 在函数开始时,通过 TRACEI 函数和 StringFromIID 函数输出一些信息,包括 riid 参数的 GUID。
    2. 接着,它创建一个名为 guid 的指针,并通过 StringFromIID 函数将 riid 转换为字符串形式,并将结果存储在 guid 中。
    3. 然后,它调用 _SDOLGetModule 函数,传递 riidintf 作为参数,以尝试获取模块。
    4. 如果 _SDOLGetModule 返回 false(表示获取模块失败),它接着调用 _igwGetModule 函数,再次尝试获取模块。
    5. 如果成功获取到模块,它再次输出 riid 的信息,然后返回 SDOL_ERRORCODE_OK 表示成功。
    6. 如果两次尝试都没有成功获取模块,它最终返回 SDOL_ERRORCODE_FAILED 表示失败。
  • 总的来说,这段代码的目的是尝试获取一个模块,首先通过 _SDOLGetModule 尝试,如果失败再通过 _igwGetModule 尝试。如果成功获取到模块,它返回成功状态码,否则返回失败状态码。

int WINAPI SDOLTerminal()
{
TRACET();
TRACEI(_T(“”));

​ int ret = ModuleLoginSDK::Destroy();

​ SAFE_DELETE(g_pSDOLLogin);

​ return ret == ShutdownSuccess ? SDOL_ERRORCODE_OK : SDOL_ERRORCODE_FAILED;

}

代码解释:

  • 这段代码是一个名为 SDOLTerminal 的函数的实现,以下是它的主要功能:
    1. 在函数开始时,通过 TRACEI 函数输出一些信息,用于调试和日志记录。
    2. 接着,它调用 ModuleLoginSDK::Destroy() 函数,该函数可能用于销毁一些模块相关的资源和对象。
    3. ModuleLoginSDK::Destroy() 返回的结果存储在 ret 变量中,这个结果可能是一个表示销毁操作是否成功的值。
    4. 然后,它通过 SAFE_DELETE(g_pSDOLLogin) 来释放 g_pSDOLLogin 所指向的对象或资源。这个宏可能用于安全地删除指针,并将指针置为 nullptr
    5. 最后,如果 ret 的值等于 ShutdownSuccess,它返回 SDOL_ERRORCODE_OK 表示终止成功,否则返回 SDOL_ERRORCODE_FAILED 表示终止失败。
  • 这段代码的主要目的是在应用程序终止时执行一些清理操作,包括销毁模块相关的资源和对象,然后返回适当的状态码以表示终止的结果。

bool _SDOLGetModule(REFIID riid, void** intf)
{
TRACET();
TRACEI(_T(“”));

​ if(riid == __uuidof(ISDOLLogin))
​ {
intf = (void)(ISDOLLogin*)g_pSDOLLogin;
​ return true;
​ }
​ if(riid == __uuidof(ISDOLLogin2))
​ {
intf = (void)(ISDOLLogin2*)g_pSDOLLogin;
​ return true;
​ }
​ if (riid == __uuidof(ISDOLInfo))
​ {
intf = (void)(ISDOLInfo*)g_pSDOLInfo;
​ return true;
​ }
​ if(riid == __uuidof(ISDOLLogin3))
​ {
intf = (void)(ISDOLLogin3*)g_pSDOLLogin;
​ return true;
​ }
​ if(riid == __uuidof(ISDOLLogin4))
​ {
intf = (void)(ISDOLLogin4*)g_pSDOLLogin;
​ return true;
​ }
​ if(riid == __uuidof(ISDOLLogin5))
​ {
intf = (void)(ISDOLLogin5*)g_pSDOLLogin;
​ return true;
​ }
​ if(riid == __uuidof(ISDOLLogin6))
​ {
intf = (void)(ISDOLLogin6*)g_pSDOLLogin;
​ return true;
​ }
​ if(riid == __uuidof(ISDOLLogin7))
​ {
intf = (void)(ISDOLLogin7*)g_pSDOLLogin;
​ return true;
​ }
​ if(riid == __uuidof(ISDOLLogin8))
​ {
intf = (void)(ISDOLLogin8*)g_pSDOLLogin;
​ return true;
​ }

​ return false;

};

代码解释:

  • 这段代码是一个名为 _SDOLGetModule 的函数的实现,以下是它的主要功能:
    1. 在函数开始时,通过 TRACEI 函数输出一些信息,用于调试和日志记录。
    2. 然后,它检查传入的 riid 参数是否等于特定的接口类型的 UUID(GUID)。如果 riid 匹配某个特定接口类型的 UUID,它将将 *intf 指向相应的接口指针,并返回 true 表示成功。
    3. 如果 riid 不匹配任何已知的接口类型,它返回 false 表示失败。
  • 这段代码的主要目的是根据传入的 riid 参数,尝试获取对应的接口,并将接口指针存储在 *intf 中,以便其他部分的代码可以使用这些接口进行操作。如果 riid 匹配已知接口类型,则返回 true,否则返回 false。这通常用于实现 COM 接口的获取和对象的实例化。

bool _igwGetModule(REFIID riid, void** intf)
{
if(riid == __uuidof(ISDOAApp))
{
intf = (void)(ISDOAApp*)g_pSDOAApp4;
return true;
}
if(riid == __uuidof(ISDOAApp2))
{
intf = (void)(ISDOAApp2*)g_pSDOAApp4;
return true;
}
if(riid == __uuidof(ISDOAApp3))
{
intf = (void)(ISDOAApp3*)g_pSDOAApp4;
return true;
}
if(riid == __uuidof(ISDOAApp4))
{
intf = (void)(ISDOAApp4*)g_pSDOAApp4;
return true;
}
if(riid == __uuidof(IGW2::ISDOAAppEx))
{
intf = (void)(IGW2::ISDOAAppEx*)g_pSDOAAppEx;
return true;
}
if(riid == __uuidof(ISDOAAppUtils))
{
intf = (void)(ISDOAAppUtils*)g_pSDOAAppUtils;
return true;
}
if(riid == __uuidof(ISDOAClientService))
{
intf = (void)(ISDOAClientService*)g_pSDOAClientService;
return true;
}

​ if(riid == __uuidof(IGPLUSApp))
​ {
intf = (void)(IGPLUSApp*)CGPlusManager::GetInstance()->getGplusAppObject();
​ return true;
​ }

​ //if(Dx7GetModule(riid, intf))
​ //{
​ // return true;
​ //}
​ if(Dx8GetModule(riid, intf))
​ {
​ return true;
​ }
​ if(Dx9GetModule(riid, intf))
​ {
​ return true;
​ }
​ if(Dx11GetModule(riid, intf))
​ {
​ return true;
​ }
​ if(GDIGetModule(riid, intf))
​ {
​ return true;
​ }
​ if(DDrawGetModule(riid, intf))
​ {
​ return true;
​ }
​ return false;

}

代码解释:

  • 这段代码是一个名为 _igwGetModule 的函数的实现,以下是它的主要功能:

    1. 它检查传入的 riid 参数是否等于特定的接口类型的 UUID(GUID)。如果 riid 匹配某个特定接口类型的 UUID,它将将 *intf 指向相应的接口指针,并返回 true 表示成功。
    2. 如果 riid 不匹配已知的接口类型,它继续检查其他接口类型,包括 Dx8GetModuleDx9GetModuleDx11GetModuleGDIGetModuleDDrawGetModule 等。如果传入的 riid 匹配这些接口类型中的任何一个,它同样将 *intf 指向相应的接口指针,并返回 true 表示成功。
    3. 如果所有的检查都失败,它最终返回 false 表示没有匹配的接口。
  • 这段代码的主要目的是根据传入的 riid 参数,尝试获取对应的接口,并将接口指针存储在 *intf 中,以便其他部分的代码可以使用这些接口进行操作。这是一种通用的接口获取机制,用于获取不同接口类型的对象。如果 riid 匹配已知的接口类型,它返回 true,否则返回 false。这通常用于实现 COM 接口的获取和对象的实例化。

解释如何调用到sdologinsdk.dll或者sdologinsdk64.dll库中的三个函数:

LIBRARY “sdologinsdk”

EXPORTS
SDOLInitialize
SDOLGetModule
SDOLTerminal
igwInitialize
igwGetModule
igwTerminal

代码解释:

  • 这段代码定义了一个名为 “sdologinsdk” 的动态链接库(DLL)的导出符号,它列出了一系列函数名称,这些函数将会在该 DLL 中被导出,以便其他模块或程序可以通过动态链接的方式调用这些函数。导出的函数包括了:
    1. SDOLInitialize
    2. SDOLGetModule
    3. SDOLTerminal
    4. igwInitialize
    5. igwGetModule
    6. igwTerminal
  • 这些导出函数通常是其他程序或模块需要使用的接口。通过将它们导出,其他程序可以在运行时动态加载这个 DLL,并使用这些函数来执行特定的操作。这种方式通常用于插件系统或模块化的应用程序,允许不同的模块或插件在运行时添加到应用程序中,以扩展其功能。

到了这里,关于typedef函数代码段解释以及部分Windows下的系统函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【聚类算法】带你轻松搞懂K-means聚类(含代码以及详细解释)

    聚类是一个将数据集中 在某些方面相似的数据成员 进行分类组织的过程,聚类就是一种发现这种内在结构的技术,聚类技术经常被称为 无监督学习 。 k均值聚类是最著名的划分聚类算法,由于简洁和效率使得他成为所有聚类算法中最广泛使用的。给定一个数据点集合和需要

    2024年02月01日
    浏览(37)
  • Windows下的QT系统开发环境搭建

            QT是一款由Qt Company开发的跨平台C++图形用户界面 应用程序 开发框架。它既可以开发 GUI 程序,也可用于开发非GUI程序,比如 控制台 工具和服务器。Qt是面向对象的框架,使用特殊的 代码 生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容

    2024年02月09日
    浏览(51)
  • vben-admin 页面以及部分代码 常见问题 解析 持续更新····

    介绍 | Vben Admin (vvbin.cn) https://doc.vvbin.cn/guide/introduction.html ----------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------  

    2024年02月04日
    浏览(44)
  • Windows下的Linux子系统(WSL)

    什么是WSL WSL:Windows subsystem for Linux,是用于Windows上的Linux的子系统 作用很简单,可以在Windows系统中获取Linux系统环境,并完全直连计算机硬件,无需通过虚拟机虚拟硬件,不会影响Windows系统本身 为什么使用WSL WSL作为自Windows10以来的全新特性正逐步颠覆开发人员的选择 传统方式下

    2024年01月17日
    浏览(41)
  • Elasticsearch在Windows系统下的安装

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful web 接口。Elasticsearch 是用 Java 语言开发的,并作为 Apache 许可条款下的开放源码发布,是一种流行的企业级搜索引擎。 在使用 Elasticsearch 之前,我们需要安装 Elasticsearch。

    2024年02月02日
    浏览(30)
  • 【Linux操作系统】举例解释Linux系统编程中文件io常用的函数

    在Linux系统编程中,文件IO操作是非常常见和重要的操作之一。通过文件IO操作,我们可以打开、读取、写入和关闭文件,对文件进行定位、复制、删除和重命名等操作。本篇博客将介绍一些常用的文件IO操作函数。 1.1 原型、参数及返回值说明 1.1.1 原型: open()函数是Linux系统

    2024年02月12日
    浏览(48)
  • C++笔记之从使用函数指针和typedef到使用std::function和using

    参考笔记:C++笔记之从数组指针到函数数组指针(使用using name和std::function) code review!

    2024年02月15日
    浏览(43)
  • 如何设计WIndows系统下的单例进程程序?

    为了设计一个Windows系统下的单例进程程序,你可以遵循以下步骤: 首先,确定你的应用程序只能运行一个实例。这可以通过使用互斥量(Mutex)来实现。互斥量是一种同步对象,用于控制对共享资源的独占访问。 在应用程序的启动代码中,创建一个命名的互斥量对象。命名

    2024年01月22日
    浏览(48)
  • Windows11 22H2 系统版本 系统部分目录进行迁移

    首先一定是新装的系统,然后使用Administrator账户,因为此账户可以有更多的权限,对系统做出更改,此次修改有弊端,修改完成后,appx文件无法安装,MicrosoftWindowsStore无法安装和更新,如果有解决方案,请反馈,谢谢 所以,第一步就是切换账户,右键Windows,选择计算机管理本地用户和组用户

    2024年02月19日
    浏览(43)
  • Autodock--基于windows10系统下的详细安装教程

    本文只提供安装步骤及安装包 包括Autodock、MGLTools、python2.5的安装配置 本文所用到的软件及版本号,需要其他版本可按教程自行下载: 阿里云盘资源文件链接: https://www.aliyundrive.com/s/cZjsAutvJLJ 提取码: fx23 python官网:https://www.python.org/ download→Windows版本 下拉找到python2.5 下载

    2024年02月07日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包