PWLX_MPR_NOTIFY_INFOpNprNotifyInfo,PVOID*pProfile) {
returnp_WlxLoggedOutSAS(pWlxContext,dwSasType,pAuthenticationId, pLogonSid,pdwOptions,phToken,pNprNotifyInfo,pProfile); }
BOOLWINAPIWlxActivateUserShell(PVOIDpWlxContext,PWSTR pszDesktopName,
PWSTRpszMprLogonScript,PVOIDpEnvironment) {
returnp_WlxActivateUserShell(pWlxContext,pszDesktopName, pszMprLogonScript,pEnvironment); }
intWINAPIWlxLoggedOnSAS(PVOIDpWlxContext,DWORDdwSasType,PVOID pReserved) {
returnp_WlxLoggedOnSAS(pWlxContext,dwSasType,pReserved); }
VOIDWINAPIWlxDisplayLockedNotice(PVOIDpWlxContext) {
p_WlxDisplayLockedNotice(pWlxContext); }
intWINAPIWlxWkstaLockedSAS(PVOIDpWlxContext,DWORDdwSasType) {
returnp_WlxWkstaLockedSAS(pWlxContext,dwSasType); }
BOOLWINAPIWlxIsLockOk(PVOIDpWlxContext) {
returnp_WlxIsLockOk(pWlxContext); }
BOOLWINAPIWlxIsLogoffOk(PVOIDpWlxContext) {
returnp_WlxIsLogoffOk(pWlxContext); }
VOIDWINAPIWlxLogoff(PVOIDpWlxContext) {
p_WlxLogoff(pWlxContext); }
VOIDWINAPIWlxShutdown(PVOIDpWlxContext,DWORDShutdownType) {
p_WlxShutdown(pWlxContext,ShutdownType); }
//version1.1
BOOLWINAPIWlxScreenSaverNotify(PVOIDpWlxContext,BOOL*pSecure) {
returnp_WlxScreenSaverNotify(pWlxContext,pSecure); }
BOOLWINAPIWlxStartApplication(PVOIDpWlxContext,PWSTR pszDesktopName,
PVOIDpEnvironment,PWSTRpszCmdLine) {
returnp_WlxStartApplication(pWlxContext,pszDesktopName, pEnvironment,pszCmdLine); }
//version1.3
BOOLWINAPIWlxNetworkProviderLoad(PVOIDpWlxContext, PWLX_MPR_NOTIFY_INFOpNprNotifyInfo) {
returnp_WlxNetworkProviderLoad(pWlxContext,pNprNotifyInfo); }
BOOLWINAPIWlxDisplayStatusMessage(PVOIDpWlxContext,HDESKhDesktop, DWORDdwOptions,PWSTRpTitle,PWSTRpMessage) {
returnp_WlxDisplayStatusMessage(pWlxContext,hDesktop, dwOptions,pTitle,pMessage); }
BOOLWINAPIWlxGetStatusMessage(PVOIDpWlxContext,DWORD*pdwOptions, PWSTRpMessage,DWORDdwBufferSize) {
returnp_WlxGetStatusMessage(pWlxContext,pdwOptions,pMessage, dwBufferSize); }
BOOLWINAPIWlxRemoveStatusMessage(PVOIDpWlxContext) {
returnp_WlxRemoveStatusMessage(pWlxContext); }
通过上面的代码,用户可以发现实现一个GINA动态链接库和实现SPI方法差不
多,都需要得到原来实现动态链接库的目标函数指针。这里GINA的主要功能还是通 过调用微软提供的MSGINA实现,使用现成的GINA可以少犯错误,提高开发效率。 由于GINA动态链接库和WinLogon是同一个进程,可以使用GINA动态链接库 方便地实现APIHOOK和窗口子类化。
由于WinLogon是在调用WlxInitialize函数时决定在后面的调用时使用哪一个调 度表传递给GINA的,因此可以在WlxInitialize调用中完成函数的挂接,执行 HookWlxDialogBoxParam函数。设置((PWLX_DISPATCH_VERSION_X_X)
pWinLogonFunctions)->WlxDialogBoxParam=MyWlxDialogBoxParam,使其指向一个 新的函数过程。
intWINAPIMyWlxDialogBoxParam(HANDLE,HANDLE,LPWSTR,HWND,DLGPROC, LPARAM);
voidHookWlxDialogBoxParam(PVOIDpWinLogonFunctions,DWORD
dwWlxVersion) {
//挂接WlxDialogBoxParam() switch(dwWlxVersion) {
caseWLX_VERSION_1_0: {
pfWlxDialogBoxParam=
((PWLX_DISPATCH_VERSION_1_0)
pWinLogonFunctions)->WlxDialogBoxParam;
((PWLX_DISPATCH_VERSION_1_0)pWinLogonFunctions)->WlxDialogBoxParam= MyWlxDialogBoxParam; #ifdef_DEBUG
DEBUG_MSG(\#endif break; }
caseWLX_VERSION_1_1: {
pfWlxDialogBoxParam=((PWLX_DISPATCH_VERSION_1_1) pWinLogonFunctions)->WlxDialogBoxParam;
((PWLX_DISPATCH_VERSION_1_1)pWinLogonFunctions)->WlxDialogBoxParam= MyWlxDialogBoxParam; #ifdef_DEBUG
DEBUG_MSG(\#endif break; }
caseWLX_VERSION_1_2: {
pfWlxDialogBoxParam=((PWLX_DISPATCH_VERSION_1_2) pWinLogonFunctions)->WlxDialogBoxParam;
((PWLX_DISPATCH_VERSION_1_2)pWinLogonFunctions)->WlxDialogBoxParam= MyWlxDialogBoxParam; #ifdef_DEBUG
DEBUG_MSG(\#endif break; }
default: {
pfWlxDialogBoxParam=((PWLX_DISPATCH_VERSION_1_3) pWinLogonFunctions)->WlxDialogBoxParam;
((PWLX_DISPATCH_VERSION_1_3)pWinLogonFunctions)->WlxDialogBoxParam=
MyWlxDialogBoxParam; #ifdef_DEBUG
DEBUG_MSG(\#endif break; } } }
intWINAPIMyWlxDialogBoxParam(HANDLEhWlx,HANDLEhInst, LPWSTRlpszTemplate,HWNDhwndOwner,DLGPROCdlgprc, LPARAMdwInitParam) {
assert(pfWlxDialogBoxParam!=NULL);
//只能通过标识符号识别MSGINA对话框 if(!HIWORD(lpszTemplate)) {
//Hookappropriatedialogboxesasnecessary. switch((DWORD)lpszTemplate) {
caseIDD_WLXDIAPLAYSASNOTICE_DIALOG: {
pfWlxDisplaySASDlgProc=dlgprc;
returnpfWlxDialogBoxParam(hWlx,hInst,lpszTemplate, hwndOwner,
MyWlxDisplaySASDlgProc, dwInitParam); }
case1500:
caseIDD_WLXLOGGEDOUTSAS_DIALOG: {
pfWlxLoggedOutSASDlgProc=dlgprc;
returnpfWlxDialogBoxParam(hWlx,hInst,lpszTemplate,hwndOwner, MyWlxLoggedOutSASDlgProc,dwInitParam); }
case1900:
caseIDD_WLXWKSTALOCKEDSAS_DIALOG: {
pfWlxWkstaLockedSASDlgProc=dlgprc;
returnpfWlxDialogBoxParam(hWlx,hInst,lpszTemplate,
hwndOwner,MyWlxWkstaLockedSASDlgProc,dwInitParam); }
case1950:
caseIDD_WLXLOGGEDONSAS_DIALOG: {
pfWlxLoggedOnSASDlgProc=dlgprc;
returnpfWlxDialogBoxParam(hWlx,hInst,lpszTemplate,hwndOwner, MyWlxLoggedOnSASDlgProc,dwInitParam); }
case1700:
caseIDD_CHANGE_PASSWORD_DIALOG: {
pfChangePasswordDlgProc=dlgprc;
returnpfWlxDialogBoxParam(hWlx,hInst, lpszTemplate,hwndOwner,
MyChangePasswordDlgProc,dwInitParam); } } }
returnpfWlxDialogBoxParam(hWlx,hInst,lpszTemplate,hwndOwner, dlgprc,dwInitParam); }
BOOLCALLBACKMyWlxLoggedOutSASDlgProc(HWNDhwndDlg,UINTuMsg, WPARAMwParam,LPARAMlParam) {
BOOLbResult;
assert(pfWlxLoggedOutSASDlgProc!=NULL);
bResult=pfWlxLoggedOutSASDlgProc(hwndDlg,uMsg,wParam,lParam); if(uMsg==WM_INITDIALOG) {
DWORDdwIndex; HWNDhwndDomain;
NET_API_STATUSnetstatus;
LPWKSTA_INFO_100lpWkstaInfo;
netstatus=NetWkstaGetInfo(NULL,100,(LPBYTE*)&lpWkstaInfo); if(netstatus!=NERR_Success)returnbResult; //ConverttoANSI
wcstombs(g_szLocalMachineName,lpWkstaInfo->wki100_computername, sizeof(g_szLocalMachineName));
NetApiBufferFree((LPVOID)lpWkstaInfo);
hwndDomain=GetDlgItem(hwndDlg,IDC_WLXLOGGEDOUTSAS_DOMAIN); if(hwndDomain==NULL)returnbResult;
dwIndex=(DWORD)SendMessage(hwndDomain,CB_FINDSTRING, 0,(LPARAM)g_szLocalMachineName); if(dwIndex!=CB_ERR) {
SendMessage(hwndDomain,CB_SETCURSEL,(WPARAM)dwIndex,0); EnableWindow(hwndDomain,FALSE); }