📄 load.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/* File: pcmcia.c
*
* Purpose: WinCE device loader for PCMCIA devices
*
*/
#include <windows.h>
#include <types.h>
#include <tchar.h>
#include <winreg.h>
#include <devload.h>
#include <cardserv.h>
#include <sockserv.h>
#include <pcmcia.h>
#include <tuple.h>
#include <netui.h>
#include <extern.h>
#include <ceddk.h>
#ifdef INSTRUM_DEV
#include <instrumd.h>
#endif // INSTRUM_DEV
//
// This module contains these functions:
// QueryDriverNameThread
// QueryDriverName
// InitTapiDeviceChange
// RunDetectors
// LoadPCCardDriver
// FindPCCardDriver
// CardServLoadDriver
// CardServFreeDriver
typedef struct _QUERY_NAME_CONTEXT {
LPTSTR PnpId;
UCHAR DevType;
CARD_SOCKET_HANDLE hSock;
} QUERY_NAME_CONTEXT, * PQUERY_NAME_CONTEXT;
typedef LPTSTR (*PFN_INSTALL_DRIVER)(LPTSTR, LPTSTR, DWORD);
CRITICAL_SECTION v_DetectCrit;
CRITICAL_SECTION v_FindDriverCrit;
static BOOL LoadPCCardDriver(CARD_SOCKET_HANDLE hSock, LPTSTR PnpId, LPTSTR DevName, LPTSTR RegPath);
//
// Thread to query the user for the name of the driver for
// an unrecognized pccard, call its Install_Driver function and
// start it.
//
static DWORD
QueryDriverNameThread(
IN PVOID ThreadContext
)
{
PQUERY_NAME_CONTEXT pContext = (PQUERY_NAME_CONTEXT)ThreadContext;
HMODULE hInstallDll;
PFN_INSTALL_DRIVER pfnInstall;
LPTSTR RegPath = NULL;
GETDRIVERNAMEPARMS GDNP;
PLOG_SOCKET pLsock;
if (v_hGwesEvent == NULL) {
goto qdnt_exit;
}
WaitForSingleObject(v_hGwesEvent, INFINITE);
if (!IsCardInserted(pContext->hSock.uSocket)) {
goto qdnt_exit;
}
GDNP.PCCardType = (DWORD)pContext->DevType;
GDNP.Socket = (DWORD)pContext->hSock.uSocket;
//
// Get this unrecognized card's device driver name.
//
if (!CallGetDriverName(NULL, &GDNP)) {
DEBUGMSG(ZONE_INIT, (TEXT("DEVICE: CallGetDriverName failed %d\r\n"),
GetLastError()));
goto qdnt_exit;
}
EnterCriticalSection(&v_FindDriverCrit);
pLsock = I_FindSocket(pContext->hSock);
if (pLsock != NULL &&
GetCurrentThreadId() == pLsock->hQueryDriver) {
pLsock->hQueryDriver = 0;
} else {
DEBUGMSG(ZONE_ERROR,
(TEXT("QueryDriverNameThread: Logical socket no longer exists/QueryDriverThread has been replaced.\r\n")));
}
LeaveCriticalSection(&v_FindDriverCrit);
DEBUGMSG(ZONE_INIT,
(TEXT("DEVICE: CallGetDriverName returned %s\r\n"), GDNP.DriverName));
hInstallDll = LoadDriver(GDNP.DriverName);
if (hInstallDll == NULL) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("DEVICE: LoadDriver(%s) failed %d\r\n"),
GDNP.DriverName, GetLastError()));
goto qdnt_exit;
}
pfnInstall = (PFN_INSTALL_DRIVER)GetProcAddress(hInstallDll,
TEXT("Install_Driver"));
//
// Tell it to install itself
//
if (pfnInstall) {
__try {
RegPath = pfnInstall(
pContext->PnpId,
GDNP.DriverName,
sizeof(GDNP.DriverName));
} __except (EXCEPTION_EXECUTE_HANDLER) {
RETAILMSG(1, (TEXT("PCMCIA:QueryDriverName install func in %s faulted!\n"),
GDNP.DriverName));
}
}
//
// Start it
//
if (RegPath) {
LoadPCCardDriver(pContext->hSock, pContext->PnpId, NULL, RegPath);
}
FreeLibrary(hInstallDll);
qdnt_exit:
LocalFree(pContext->PnpId);
LocalFree(pContext);
return 0;
} // QueryDriverNameThread
//
// Function to start a thread to query the user for the name of the driver for
// an unrecognized pccard.
//
static VOID
QueryDriverName(
LPTSTR PnpId,
UCHAR DevType,
CARD_SOCKET_HANDLE hSock
)
{
HANDLE hThd;
LPTSTR pPnpId;
PQUERY_NAME_CONTEXT pContext;
DWORD cExtra;
PLOG_SOCKET pLsock = I_FindSocket(hSock);
pContext = LocalAlloc(LPTR, sizeof(QUERY_NAME_CONTEXT));
if (pContext == NULL) {
return;
}
cExtra = (hSock.uFunction > 0) ? 3 : 1;
pPnpId = LocalAlloc(LPTR, (_tcslen(PnpId) + cExtra) * sizeof(TCHAR));
if (pPnpId == NULL) {
LocalFree(pContext);
return;
}
_tcscpy(pPnpId, PnpId);
//
// Additional functions will have a "-n" appended to their PnpId where
// 'n' is the function number. This is so we can have a PnpId registry
// entry for each function.
//
if (hSock.uFunction > 0) {
cExtra = _tcslen(pPnpId);
pPnpId[cExtra] = (TCHAR) '-';
pPnpId[cExtra+1] = (TCHAR) '0' + (TCHAR) hSock.uFunction;
pPnpId[cExtra+2] = (TCHAR) 0;
}
pContext->PnpId = pPnpId;
pContext->DevType = DevType;
pContext->hSock = hSock;
EnterCriticalSection(&v_FindDriverCrit);
hThd = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)&QueryDriverNameThread,
(LPVOID) pContext, 0, (pLsock == NULL) ? NULL : &pLsock->hQueryDriver);
if (hThd != NULL) {
CloseHandle(hThd);
} else {
LocalFree(pPnpId);
LocalFree(pContext);
}
LeaveCriticalSection(&v_FindDriverCrit);
} // QueryDriverName
//
// RunDetectors - Function to call the detection modules under the key
// HLM\Drivers\PCMCIA\Detect and return the key name under HLM\Drivers\PCMCIA
// for the device driver to load (will be passed to LoadPCCardDriver), or return
// NULL if none of the detection modules recognizes the card.
// The names of the keys under HLM\Drivers\PCMCIA\Detect are actually numbers to
// allow a definite ordering of the detection modules.
//
static LPTSTR
RunDetectors(
CARD_SOCKET_HANDLE hSock,
UCHAR DevType,
LPTSTR StrBuf,
DWORD StrLen
)
{
HKEY hDetectKey;
HKEY hDetectMod;
PFN_DETECT_ENTRY pfnDetectEntry;
TCHAR DetectDll[DEVDLL_LEN];
TCHAR DetectEntry[DEVENTRY_LEN];
LPTSTR DeviceKey;
DWORD status;
DWORD ValLen;
DWORD ValType;
DWORD NumDetectKeys;
DWORD RegEnum;
DWORD DetectOrder;
HMODULE hDetectDll;
status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
DEVLOAD_DETECT_KEY,
0,
0,
&hDetectKey);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("PCMCIA:RunDetectors: RegOpenKeyEx(%s) returned %d\r\n"),
DEVLOAD_DETECT_KEY, status));
return FALSE;
}
//
// See how many detection modules there are
//
RegEnum = sizeof(DetectDll)/sizeof(TCHAR);
status = RegQueryInfoKey(
hDetectKey,
DetectDll, // class name buffer (lpszClass)
&RegEnum, // ptr to length of class name buffer (lpcchClass)
NULL, // reserved
&NumDetectKeys, // ptr to number of subkeys (lpcSubKeys)
&ValType, // ptr to longest subkey name length (lpcchMaxSubKeyLen)
&ValLen, // ptr to longest class string length (lpcchMaxClassLen)
&DetectOrder, // ptr to number of value entries (lpcValues)
&DetectOrder, // ptr to longest value name length (lpcchMaxValueNameLen)
&ValLen, // ptr to longest value data length (lpcbMaxValueData)
NULL, // ptr to security descriptor length
NULL); // ptr to last write time
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("PCMCIA:RunDetectors: RegQueryInfoKey() returned %d.\r\n"),
status));
goto rd_end;
}
DEBUGMSG(ZONE_INIT,
(TEXT("PCMCIA:RunDetectors: %d detection modules\r\n"), NumDetectKeys));
//
// Call the detection modules in numeric order. (The key names are numbers).
//
DetectOrder = 0;
while (NumDetectKeys) {
//
// First check if the user yanked the card.
//
if (IsCardInserted(hSock.uSocket) == FALSE) {
goto rd_end;
}
//
// Find the next detection module
//
wsprintf(DetectDll, TEXT("%02d"), DetectOrder); // format key name
status = RegOpenKeyEx(hDetectKey, DetectDll, 0, 0, &hDetectMod);
if (status) {
goto rd_next_detector1;
}
NumDetectKeys--;
//
// Get the detection module's DLL name
//
ValLen = sizeof(DetectDll);
status = RegQueryValueEx(
hDetectMod,
DEVLOAD_DLLNAME_VALNAME,
NULL,
&ValType,
(PUCHAR)&DetectDll[0],
&ValLen);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("PCMCIA:RunDetectors: RegQueryValueEx(%d\\DetectDll) returned %d\r\n"),
DetectOrder, status));
goto rd_next_detector;
}
//
// Get the detection module's entrypoint
//
ValLen = sizeof(DetectEntry);
status = RegQueryValueEx(
hDetectMod,
DEVLOAD_ENTRYPOINT_VALNAME,
NULL,
&ValType,
(PUCHAR)DetectEntry,
&ValLen);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("PCMCIA:RunDetectors: RegQueryValueEx(%d\\DetectEntry) returned %d\r\n"),
DetectOrder, status));
goto rd_next_detector;
}
//
// Load the detection module and get the address of its entrypoint
//
hDetectDll = LoadDriver(DetectDll);
if (hDetectDll == NULL) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("PCMCIA:RunDetectors: LoadLibrary(%s) failed %d\r\n"),
DetectDll, GetLastError()));
goto rd_next_detector;
}
pfnDetectEntry = (PFN_DETECT_ENTRY) GetProcAddress(hDetectDll, DetectEntry);
if (pfnDetectEntry == NULL) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("PCMCIA:RunDetectors: GetProcAddr(%s, %s) failed %d\r\n"),
DetectDll, DetectEntry, GetLastError()));
FreeLibrary(hDetectDll);
goto rd_next_detector;
}
//
// Finally, call the detection module's entrypoint
//
DEBUGMSG(ZONE_INIT,
(TEXT("PCMCIA:RunDetectors: calling %d:%s:%s\r\n"),
DetectOrder, DetectDll, DetectEntry));
__try {
DeviceKey = (pfnDetectEntry)(hSock, DevType, StrBuf, StrLen);
} __except (EXCEPTION_EXECUTE_HANDLER) {
DEBUGMSG(ZONE_INIT,
(TEXT("PCMCIA:RunDetectors: faulted in %s:%s, continuing\r\n"),
DetectDll, DetectEntry));
DeviceKey = NULL;
}
FreeLibrary(hDetectDll);
if (DeviceKey) {
DEBUGMSG(ZONE_INIT,
(TEXT("PCMCIA:RunDetectors: %d:%s:%s returned %s\r\n"),
DetectOrder, DetectDll, DetectEntry, DeviceKey));
RegCloseKey(hDetectKey);
RegCloseKey(hDetectMod);
return DeviceKey;
}
rd_next_detector:
RegCloseKey(hDetectMod);
rd_next_detector1:
DetectOrder++;
}
rd_end:
RegCloseKey(hDetectKey);
return NULL;
} // RunDetectors
//
// Function to start a driver in the devload manner or to LoadDriver(devdll)
// and GetProcAddress(entry) and call an entrypoint.
//
// Return FALSE only if the driver key does not exist in the registry.
//
static BOOL
LoadPCCardDriver(
CARD_SOCKET_HANDLE hSock,
LPTSTR PnpId,
LPTSTR DevName,
LPTSTR RegPath
)
{
HKEY hDevKey;
PFN_DEV_ENTRY pfnEntry;
TCHAR DevDll[DEVDLL_LEN];
TCHAR DevEntry[DEVENTRY_LEN];
TCHAR RegBuf[DEVKEY_LEN];
TCHAR PnpMFCId[DEVKEY_LEN];
DWORD status, intrpend;
DWORD ValLen;
DWORD ValType;
HMODULE hDevDll;
PLOG_SOCKET pLsock = I_FindSocket(hSock);
//
// Format the registry path for this device.
//
if (RegPath == NULL) {
RegPath = RegBuf;
_tcscpy(RegPath, DEVLOAD_PCMCIA_KEY);
_tcscat(RegPath, TEXT("\\"));
if (DevName == NULL) {
ValLen = _tcslen(RegPath);
_tcsncpy(RegPath + ValLen, PnpId, DEVKEY_LEN - (ValLen + 2));
RegPath[DEVKEY_LEN - 3] = 0;
//
// Additional functions will have a "-n" appended to their PnpId where
// 'n' is the function number. This is so we can have a PnpId registry
// entry for each function.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -