/*-------------------------------------------------------------- * * FILE: SKEYDLL.C * * PURPOSE: The file contains the SerialKeys DLL Functions * * CREATION: June 1994 * * COPYRIGHT: Black Diamond Software (C) 1994 * * AUTHOR: Ronald Moak * * $Header: %Z% %F% %H% %T% %I% * *------------------------------------------------------------*/ #include "windows.h" #include "..\skeys\sk_dllif.h" #include "..\skeys\sk_dll.h" #include "..\skeys\sk_reg.h" #include "skeys.h" #include #include "w95trace.c" #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define RUNNINGEVENT TEXT("SkeysRunning") #define ONE_MINUTE (60 * 1000) static BOOL SerialKeysInstall(void); static BOOL IsSerialKeysRunning(); static BOOL IsServiceStartAllowed(); static BOOL WaitForServiceRunning(); /*--------------------------------------------------------------- * * FUNCTION int APIENTRY LibMain * * TYPE Global * * PURPOSE LibMain is called by Windows when * the DLL is initialized, Thread Attached, and other times. * Refer to SDK documentation, as to the different ways this * may be called. * * The LibMain function should perform additional initialization * tasks required by the DLL. In this example, no initialization * tasks are required. LibMain should return a value of 1 if * the initialization is successful. * * INPUTS * * RETURNS TRUE - Transfer Ok * FALSE- Transfer Failed * *---------------------------------------------------------------*/ INT APIENTRY LibMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved) { return 1; UNREFERENCED_PARAMETER(hInst); UNREFERENCED_PARAMETER(ul_reason_being_called); UNREFERENCED_PARAMETER(lpReserved); } /*--------------------------------------------------------------- * * FUNCTION void SkeyGetRegistryValues() * * TYPE Global * * PURPOSE Reads the values from the registry into the * SerialKeys structure * * INPUTS None * * RETURNS None * *---------------------------------------------------------------*/ static BOOL SkeyGetRegistryValues(HKEY hkey, LPSERIALKEYS psk) { LONG lErr; DWORD dwType; DWORD cbData; psk->iPortState = 0; psk->iActive = 0; psk->dwFlags = 0; cbData = sizeof(psk->dwFlags); lErr = RegQueryValueEx( hkey, REG_FLAGS, 0, &dwType, (LPBYTE)&psk->dwFlags, &cbData); if (ERROR_SUCCESS != lErr || dwType != REG_DWORD) { psk->dwFlags = 0; } psk->dwFlags |= SERKF_AVAILABLE; if (NULL != psk->lpszActivePort) { cbData = MAX_PATH * sizeof(*psk->lpszActivePort); lErr = RegQueryValueEx( hkey, REG_ACTIVEPORT, 0, &dwType, (LPBYTE)psk->lpszActivePort, &cbData); psk->lpszActivePort[ MAX_PATH - 1 ] = '\0'; // ports are all MAX_PATH tchars if (ERROR_SUCCESS != lErr || dwType != REG_SZ) { lstrcpy(psk->lpszActivePort, TEXT("COM1")); } } if (NULL != psk->lpszPort) { cbData = MAX_PATH * sizeof(*psk->lpszPort); lErr = RegQueryValueEx( hkey, REG_PORT, 0, &dwType, (LPBYTE)psk->lpszPort, &cbData); psk->lpszPort[ MAX_PATH - 1 ] = '\0'; // ports are all MAX_PATH tchars if (ERROR_SUCCESS != lErr || dwType != REG_SZ) { lstrcpy(psk->lpszPort, TEXT("COM1")); } } cbData = sizeof(psk->iBaudRate); lErr = RegQueryValueEx( hkey, REG_BAUD, 0,&dwType, (LPBYTE)&psk->iBaudRate, &cbData); if (ERROR_SUCCESS != lErr || dwType != REG_DWORD) { psk->iBaudRate = 300; } return TRUE; } /*--------------------------------------------------------------- * * FUNCTION BOOL SkeyGetUserValues() * * TYPE Local * * PURPOSE Read the registery an collect the data for the current * user. * * RETURNS TRUE - User wants Serial Keys Enabled * FALSE- User wants Serial Keys Disabled * *---------------------------------------------------------------*/ BOOL SkeyGetUserValues(LPSERIALKEYS psk) { BOOL fOk = FALSE; HKEY hkey; DWORD dwRet; DWORD dwDisposition; dwRet = RegCreateKeyEx( HKEY_CURRENT_USER, TEXT("Control Panel\\Accessibility\\SerialKeys"), 0, NULL, // CLASS NAME?? 0, // by default is non-volatile KEY_READ, NULL, // default security descriptor &hkey, &dwDisposition); // yes we throw this away if (ERROR_SUCCESS == dwRet) { fOk = SkeyGetRegistryValues(hkey, psk); RegCloseKey(hkey); } if (fOk) { // Not available unless the service is running or this // user can start it if (IsSerialKeysRunning() || IsServiceStartAllowed()) { psk->dwFlags |= SERKF_AVAILABLE; } else { psk->dwFlags &= ~SERKF_AVAILABLE; } } return(fOk); } /*--------------------------------------------------------------- * * FUNCTION void SetRegistryValues() * * TYPE Global * * PURPOSE Writes the values in the SerialKeys structure to * the Registry. * * INPUTS None * * RETURNS None * *---------------------------------------------------------------*/ static BOOL SkeySetRegistryValues(HKEY hkey, LPSERIALKEYS psk) { LONG lErr; BOOL fOk; DWORD dwFlags; dwFlags = psk->dwFlags | SERKF_AVAILABLE; lErr = RegSetValueEx( // Write dwFlags hkey, REG_FLAGS, 0,REG_DWORD, (CONST LPBYTE)&dwFlags, sizeof(DWORD)); fOk = (ERROR_SUCCESS == lErr); if (fOk) { lErr = RegSetValueEx( // Write Active Port hkey, REG_ACTIVEPORT, 0,REG_SZ, (CONST LPBYTE) psk->lpszActivePort, (NULL == psk->lpszActivePort) ? 0 : (lstrlen(psk->lpszActivePort) + 1) * sizeof(*psk->lpszActivePort)); fOk = (ERROR_SUCCESS == lErr); } if (fOk) { lErr = RegSetValueEx( // Write Active Port hkey, REG_PORT, 0,REG_SZ, (CONST LPBYTE)psk->lpszPort, (NULL == psk->lpszPort) ? 0 : (lstrlen(psk->lpszPort) + 1) * sizeof(*psk->lpszPort)); fOk = (ERROR_SUCCESS == lErr); } if (fOk) { lErr = RegSetValueEx( // Write Active Port hkey, REG_BAUD, 0,REG_DWORD, (CONST LPBYTE) &psk->iBaudRate, sizeof(psk->iBaudRate)); fOk = (ERROR_SUCCESS == lErr); } return fOk; } /*--------------------------------------------------------------- * * FUNCTION void SetUserValues() * * TYPE Global * * PURPOSE This function writes out information to the * registry. * * INPUTS None * * RETURNS TRUE - Write Successful * FALSE- Write Failed * *---------------------------------------------------------------*/ BOOL SkeySetUserValues(LPSERIALKEYS psk) { BOOL fOk = FALSE; HKEY hkey; DWORD dwRet; DWORD dwDisposition; dwRet = RegCreateKeyEx( HKEY_CURRENT_USER, TEXT("Control Panel\\Accessibility\\SerialKeys"), 0, NULL, // class name REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, // default security descriptor &hkey, &dwDisposition); // yes we throw this away if (ERROR_SUCCESS == dwRet) { fOk = SkeySetRegistryValues(hkey, psk); RegCloseKey(hkey); } return(fOk); } #if 0 // This old code is no longer needed //////////////////////////////////// /*--------------------------------------------------------------- * * FUNCTION BOOL IsSerialKeysInstalled(); * * TYPE Local * * PURPOSE This function passes the information from the * Serial Keys application to the Server * * INPUTS None * * RETURNS TRUE - SerialKeys is Installed * FALSE- SerialKeys Not Installed * *---------------------------------------------------------------*/ static BOOL IsSerialKeysInstalled() { SC_HANDLE schService = NULL; SC_HANDLE schSCManager = NULL; BOOL fOk = FALSE; // // Check if the Serial Keys Service is installed schSCManager = OpenSCManager ( NULL, // machine (NULL == local) NULL, // database (NULL == default) SC_MANAGER_ALL_ACCESS // access required ); if (NULL != schSCManager) { schService = OpenService(schSCManager, "SerialKeys", SERVICE_ALL_ACCESS); if (NULL != schService) { CloseServiceHandle(schService); fOk = TRUE; } CloseServiceHandle(schSCManager); } return fOk; } #endif //////////////////////////////////////////////////////////////////////// BOOL IsSerialKeysRunning() { BOOL fRunning = FALSE; HANDLE hEventSkeysServiceRunning; hEventSkeysServiceRunning = OpenEvent(SYNCHRONIZE, FALSE, RUNNINGEVENT); if (NULL != hEventSkeysServiceRunning) { DWORD dwWait; dwWait = WaitForSingleObject(hEventSkeysServiceRunning, 0); fRunning = (WAIT_OBJECT_0 == dwWait); CloseHandle(hEventSkeysServiceRunning); } return fRunning; } BOOL IsServiceStartAllowed() { BOOL fServiceStartAllowed = FALSE; SC_HANDLE schSCManager = NULL; schSCManager = OpenSCManager( // Open Service Manager NULL, // machine (NULL == local) NULL, // database (NULL == default) SC_MANAGER_CREATE_SERVICE); // access required if (NULL != schSCManager) // Did Open Service succeed? { CloseServiceHandle(schSCManager); fServiceStartAllowed = TRUE; } return fServiceStartAllowed; } BOOL SkeyServiceRequest(UINT uAction, LPSERIALKEYS psk, BOOL fWinIni) { BOOL fOk = FALSE; SKEYDLL SKeyDLL; DWORD bytesRead; if (IsSerialKeysRunning()) { memset(&SKeyDLL, 0, sizeof(SKeyDLL)); SKeyDLL.Message = uAction; if (psk->lpszActivePort != NULL) { strcpy(SKeyDLL.szActivePort,psk->lpszActivePort); } if (psk->lpszPort != NULL) { strcpy(SKeyDLL.szPort,psk->lpszPort); } SKeyDLL.dwFlags = psk->dwFlags | SERKF_AVAILABLE; SKeyDLL.iBaudRate = psk->iBaudRate; SKeyDLL.iPortState = psk->iPortState; SKeyDLL.iSave = fWinIni; fOk = CallNamedPipe( SKEY_NAME, // Pipe name &SKeyDLL, sizeof(SKeyDLL), &SKeyDLL, sizeof(SKeyDLL), &bytesRead, NMPWAIT_USE_DEFAULT_WAIT); if (fOk) { if (psk->lpszActivePort != NULL) { strcpy(psk->lpszActivePort,SKeyDLL.szActivePort); } if (psk->lpszPort != NULL) { strcpy(psk->lpszPort,SKeyDLL.szPort); } psk->dwFlags = SKeyDLL.dwFlags | SERKF_AVAILABLE; psk->iBaudRate = SKeyDLL.iBaudRate; psk->iPortState = SKeyDLL.iPortState; } } return fOk; } BOOL SkeyInitUser() { BOOL fOk; SERIALKEYS sk; TCHAR szActivePort[MAX_PATH]; // all ports are expected to be MAX_PATH tchars TCHAR szPort[MAX_PATH]; // all ports are expected to be MAX_PATH tchars memset(&sk, 0, sizeof(sk)); sk.cbSize = sizeof(sk); sk.lpszActivePort = szActivePort; sk.lpszPort = szPort; fOk = SkeyGetUserValues(&sk); if (fOk) { fOk = SkeyServiceRequest(SPI_SETSERIALKEYS, &sk, FALSE); } return fOk; } /*--------------------------------------------------------------- * * FUNCTION int APIENTRY SKEY_SystemParameterInfo * * TYPE Global * * PURPOSE This function passes the information from the * Serial Keys application to the Server * * INPUTS * * RETURNS TRUE - Transfer Ok * FALSE- Transfer Failed * *---------------------------------------------------------------*/ BOOL APIENTRY SKEY_SystemParametersInfo( UINT uAction, UINT uParam, LPSERIALKEYS psk, BOOL fWinIni) { BOOL fOk; BOOL fStarted; fOk = ((uAction == SK_SPI_INITUSER) || (NULL != psk && (0 != psk->cbSize))); if (fOk) { switch (uAction) { case SPI_SETSERIALKEYS: fOk = SkeySetUserValues(psk); if (fOk && (psk->dwFlags & SERKF_SERIALKEYSON) && IsServiceStartAllowed()) { fOk = SerialKeysInstall(); } if (fOk && IsSerialKeysRunning()) { fOk = SkeyInitUser(); } break; case SPI_GETSERIALKEYS: fOk = SkeyGetUserValues(psk); if (fOk && (psk->dwFlags & SERKF_SERIALKEYSON) && !IsSerialKeysRunning() && IsServiceStartAllowed()) { fOk = SerialKeysInstall(); } if (fOk && IsSerialKeysRunning()) { fOk = SkeyInitUser(); } break; case SK_SPI_INITUSER: // give the service a chance to start fStarted = WaitForServiceRunning(); if (!fStarted) { // service does not seem to be running // let's try to start it fOk = SkeyGetUserValues(psk); if (fOk && (psk->dwFlags & SERKF_SERIALKEYSON) && !IsSerialKeysRunning() && IsServiceStartAllowed()) { SerialKeysInstall(); } if (IsSerialKeysRunning()) { fOk = SkeyInitUser(); } } break; default: fOk = FALSE; // No - Fail } } return fOk; } /*****************************************************************************/ /* WaitForServiceRunning - wait up to one minute for the SerialKeys service * to signal it is ready. CreateEvent has been called by SKeys.exe before * this function is executed. */ BOOL WaitForServiceRunning() { BOOL fOk = FALSE; HANDLE hEventSkeysServiceRunning = OpenEvent(SYNCHRONIZE, FALSE, RUNNINGEVENT); if (hEventSkeysServiceRunning) { DWORD dwWait = WaitForSingleObject(hEventSkeysServiceRunning, ONE_MINUTE); CloseHandle(hEventSkeysServiceRunning); fOk = (WAIT_OBJECT_0 == dwWait); } return fOk; } /****************************************************************************/ BOOL SerialKeysInstall(void) { BOOL fStarted = FALSE; SERVICE_STATUS ssStatus; DWORD dwOldCheckPoint; TCHAR szFileName[MAX_PATH + 1]; SC_HANDLE schService = NULL; SC_HANDLE schSCManager = NULL; schSCManager = OpenSCManager( // Open Service Manager NULL, // machine (NULL == local) NULL, // database (NULL == default) SC_MANAGER_ALL_ACCESS); // access required if (NULL != schSCManager) // Did Open Service succeed? { schService = OpenService( schSCManager , __TEXT("SerialKeys"), SERVICE_ALL_ACCESS); if (NULL != schService) { // insure the serivce is auto-start ChangeServiceConfig( schService, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, // when to start service SERVICE_NO_CHANGE, // severity if service fails to start NULL, // pointer to service binary file name NULL, // pointer to load ordering group name NULL, // pointer to variable to get tag identifier NULL, // pointer to array of dependency names NULL, // pointer to account name of service NULL, // pointer to password for service account __TEXT("SerialKeys")); // name to display } else { if (!GetWindowsDirectory(szFileName, ARRAY_SIZE(szFileName))) return FALSE; // PREFIX #113665 don't use szFileName if call fails lstrcat(szFileName, __TEXT("\\system32\\skeys.exe")); // Is Service File installed? if (0xFFFFFFFF != GetFileAttributes(szFileName)) { schService = CreateService( schSCManager, // SCManager database __TEXT("SerialKeys"), // name of service __TEXT("SerialKeys"), // name to display SERVICE_ALL_ACCESS, // desired access SERVICE_WIN32_OWN_PROCESS, // service type SERVICE_AUTO_START, // start type SERVICE_ERROR_NORMAL, // error control type szFileName, // service's binary NULL, // no load ordering group NULL, // no tag identifier NULL, // no dependencies NULL, // LocalSystem account NULL); // no password } } if (NULL != schService) { BOOL fOk = QueryServiceStatus(schService,&ssStatus); if (fOk && ssStatus.dwCurrentState != SERVICE_RUNNING) { static PTSTR pszArg = TEXT("F\0"); // force service to start PTSTR apszArg[] = {pszArg, NULL}; if (StartService(schService, 1, apszArg)) { while(fOk && ssStatus.dwCurrentState != SERVICE_RUNNING) { dwOldCheckPoint = ssStatus.dwCheckPoint; Sleep(max(ssStatus.dwWaitHint, 1000)); fOk = QueryServiceStatus(schService,&ssStatus); fOk = (fOk && (dwOldCheckPoint >= ssStatus.dwCheckPoint)); } } } fStarted = fOk && (ssStatus.dwCurrentState == SERVICE_RUNNING); CloseServiceHandle(schService); if (fStarted) { fStarted = WaitForServiceRunning(); } } CloseServiceHandle(schSCManager); } return fStarted; }