1 、 **MSI-XCAP 结 构**
MSI-X和MSI最大的不同是messagedata、message address和status字段没有存放在设备的配置空间中,而是使用MSI-X
Table structure和MSI-X PBA structure来存放这些字段。
MSI-X Table structure和PBA
structure存放在设备的BAR空间里,这两个structure可以map到相同BAR,也可以map到不同BAR,但是这个BAR必须是memory
BAR而不能是IO BAR,也就是说这两个structure要map到memory空间。
注意:一个function只能支持一个MSI-X CAP。
学习LINUX源代码,在看
https://elixir.bootlin.com/linux/v5.5-rc2/source/drivers/usb/gadget/function/f_uvc.c
看到代码如下:
#define UVC_STRING_CONTROL_IDX 0
#define UVC_STRING_STREAMING_IDX 1
struct usb_string {
u8 id;
const char *s;
};
static struct usb_string uvc_en_us_strings[] = {
[UVC_STRING_CONTROL_IDX].s = "UVC Camera",
[UVC_STRING_STREAMING_IDX].s = "Video Streaming",
{ }
};
可以看到uvc_en_us_strings明显是一个数组,不过由于本人对GNU C的扩展不熟,故只能通过测试代码来验证:
#include <stdio.h>
struct st
{
int a;
char* b;
};
int main()
{
struct st s[] =
{
[1].b="000000000",
[2].b="1111111",
{}
};
int x = sizeof(s)/sizeof(s[0]);
int i =0;
for(i=0;i<x;i++)
{
printf("%d -> %s\r\n",i,s[i].b);
}
return 0;
}
代码输出为:
array num is 4
[0] -> a=0,b=(null)
[1] -> a=0,b=000000000
[2] -> a=0,b=1111111
[3] -> a=0,b=(null)
在查看Linux源代码的时候,经常会遇到一些宏le16_to_cpu之类的。如以下代码:
static int
uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
{
struct uvc_device *uvc = to_uvc(f);
struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) {
uvcg_info(f, "invalid request type\n");
return -EINVAL;
}
/* Stall too big requests. */
if (le16_to_cpu(ctrl->wLength) > UVC_MAX_REQUEST_SIZE)
return -EINVAL;
/* Tell the complete callback to generate an event for the next request
* that will be enqueued by UVCIOC_SEND_RESPONSE.
*/
uvc->event_setup_out = !(ctrl->bRequestType & USB_DIR_IN);
uvc->event_length = le16_to_cpu(ctrl->wLength);
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_SETUP;
memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req));
v4l2_event_queue(&uvc->vdev, &v4l2_event);
return 0;
}
这种其实就是大小端的问题。
在Windows编程中一般在搞网络时才会进行大小端转换,其它默认都是小端,故可以直接怱略掉。
但由于Linux要兼容各个硬件平台,有的CPU默认是小端,如X86,X64,但有些是大端的,如Power PC,故系统在外部设备如网络或者固件设备进行数据交换时,需要进行大小端的转换。
#if __BYTE_ORDER == __BIG_ENDIAN
#define cpu_to_le16 bswap_16
#define cpu_to_le32 bswap_32
#define cpu_to_le64 bswap_64
#define le16_to_cpu bswap_16
#define le32_to_cpu bswap_32
#define le64_to_cpu bswap_64
#define cpu_to_be16
#define cpu_to_be32
#define cpu_to_be64
#define be16_to_cpu
#define be32_to_cpu
#define be64_to_cpu
#else
#define cpu_to_le16
#define cpu_to_le32
#define cpu_to_le64
#define le16_to_cpu
#define le32_to_cpu
#define le64_to_cpu
#define cpu_to_be16 bswap_16
#define cpu_to_be32 bswap_32
#define cpu_to_be64 bswap_64
#define be16_to_cpu bswap_16
#define be32_to_cpu bswap_32
#define be64_to_cpu bswap_64
#endif
可以看到,当大小不同时,需要转换的。
- CPU就是处理器,可大端,可小端。根据架构决定
- le就是little endian
UVC摄像头一般有2个接口,分别是视频控制接口和视频流接口。
视频控制接口是必须的,但是视频流接口根据UVC1.5规范定义可以没有即0,也可以有多个。不过对于一般的UVC相机而言,就是有一个视频流接口。
当我们对UVC相面接口判断时默认的思路如下:
是不是视频控制接口,是返回TRUE,不是再判断。
是不是视频流接口,如果是再判断是不是视频流端点启用,如果是返TRUE,否则返回FALSE.
但在今天看LINUX的源代码时:
uvc_function_get_alt(struct usb_function *f, unsigned interface)
{
struct uvc_device *uvc = to_uvc(f);
uvcg_info(f, "%s(%u)\n", __func__, interface);
if (interface == uvc->control_intf)
return 0;
else if (interface != uvc->streaming_intf)
return -EINVAL;
else
return uvc->video.ep->enabled ? 1 : 0;
}
它的思路在判断视频流接口时和我们一般的思路有区别。即判断是不是视频流接口,不是返回FALSE,else就是了,那么再判断是不是音频流端点是否启用。这种代码的思路看着是不是着着更清晰一点,也好像弥补了我们第一种思路代码写完后的有点失落感。
DWORD CUtils::DeleteDir(std::wstring strPath)
{
HANDLE Handle = NULL;
WIN32_FIND_DATA fData;
DWORD errorcode = STATUS_SUCCESS;
std::wstring strDirName = strPath + L"\\*.*";
Handle = FindFirstFile(strDirName.c_str(), &fData);
if (Handle == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
do
{
errorcode = GetLastError();
if (fData.cFileName[0] == L'.')
{
continue;
}
if (fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (strDirName[strPath.length() - 1] != '\\')
{
std::wstring strA = strPath + L'\\' + fData.cFileName;
DeleteDir(strA.c_str());
}
else
{
std::wstring strB = strPath + fData.cFileName;
DeleteDir(strB.c_str());
}
std::wstring strTemp = strPath + L"\\" + fData.cFileName;
SetFileAttributes(strTemp.c_str(), ~FILE_ATTRIBUTE_READONLY);
if (!RemoveDirectory(strTemp.c_str()))
{
errorcode = GetLastError();
}
}
else
{
std::wstring strTemp = strPath + L"\\" + fData.cFileName;
SetFileAttributes(strTemp.c_str(), ~FILE_ATTRIBUTE_READONLY);
ClearFileContent(strTemp);
if (!DeleteFile(strTemp.c_str()))
{
errorcode = GetLastError();
}
}
} while (FindNextFile(Handle, &fData));
if (errorcode == ERROR_NO_MORE_FILES)//空目录
{
::RemoveDirectory(strDirName.c_str());
errorcode = GetLastError();
}
if (Handle)
{
FindClose(Handle);
}
return errorcode;
}
#include <Wininet.h>
#pragma comment(lib, "Wininet.lib")
BOOL CUtils::HttpRequestGet(IN const std::wstring sHomeUrl, USHORT port, IN const std::wstring& sPageUrl, OUT std::string &sResult)
{
LONG nPort = port;
HINTERNET hInternet;
DWORD nGetSize;
LPSTR lpszData = NULL;
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
hInternet = InternetOpen(_T("Mozilla/4.0 (compatible; Indy Library)"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (NULL == hInternet)
{
DebugPrintA("InternetOpen err:0x%08x\n",GetLastError());
InternetCloseHandle(hInternet);
return FALSE;
}
HINTERNET hSession = InternetConnect(hInternet, sHomeUrl.c_str(), (INTERNET_PORT)nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
std::wstring sHtmlHeader;
sHtmlHeader = _T("Content-Type: application/x-www-form-urlencoded\r\n");
sHtmlHeader += _T("Accept: text/html, */*\r\n");
sHtmlHeader += _T("User-Agent: Mozilla/4.0 (compatible;Indy Library)\r\n");
HINTERNET hRequest = HttpOpenRequest(hSession, _T("GET"), sPageUrl.c_str(), _T("HTTP/1.1"), _T(""), 0, INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_NO_CACHE_WRITE, 0);
int iTimeout = 10000;
InternetSetOption(hRequest, INTERNET_OPTION_CONNECT_TIMEOUT, &iTimeout, sizeof(iTimeout));
InternetSetOption(hRequest, INTERNET_OPTION_SEND_TIMEOUT, &iTimeout, sizeof(iTimeout));
InternetSetOption(hRequest, INTERNET_OPTION_RECEIVE_TIMEOUT, &iTimeout, sizeof(iTimeout));
InternetSetOption(hRequest, INTERNET_OPTION_DATA_SEND_TIMEOUT, &iTimeout, sizeof(iTimeout));
InternetSetOption(hRequest, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, &iTimeout, sizeof(iTimeout));
InternetSetOption(hRequest, INTERNET_OPTION_LISTEN_TIMEOUT, &iTimeout, sizeof(iTimeout));
BOOL bResult = HttpSendRequest(hRequest, sHtmlHeader.c_str(), sHtmlHeader.size(), _T(""), 0);
if (FALSE == bResult)
{
DebugPrintA("HttpSendRequest err:0x%08x\n", GetLastError());
InternetCloseHandle(hRequest);
InternetCloseHandle(hSession);
InternetCloseHandle(hInternet);
return FALSE;
}
LPSTR pszResponse = new char[640 * 1024];
if (pszResponse != NULL)
{
memset(pszResponse, 0, 640 * 1024);
nGetSize = 0;
do
{
if (!InternetQueryDataAvailable(hRequest, &dwSize, 0, 0))
{
break;
}
if (InternetReadFile(hRequest, (LPVOID)&pszResponse[nGetSize], dwSize, &dwDownloaded))
{
nGetSize += dwSize;
if (dwDownloaded == 0 || nGetSize > 600 * 1024)
{
break;
}
}
} while (FALSE);
pszResponse[nGetSize] = 0;
sResult = pszResponse;
}
InternetCloseHandle(hRequest);
InternetCloseHandle(hSession);
InternetCloseHandle(hInternet);
delete[]pszResponse;
return TRUE;
}
DWORD CUtils::UpdateSysTime(char* pServer)
{
DWORD err = STATUS_SUCCESS;
ULONG IP = DNS(pServer,err);
if (IP == 0)
{
return err;
}
SOCKET soc = NULL;
do
{
soc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (soc == NULL)
{
err = GetLastError();
break;
}
ULONG nTimeOut = 5000;
if (SOCKET_ERROR == setsockopt(soc, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOut, sizeof(nTimeOut)))
{
err = GetLastError();
DebugPrintA("set sendtimeout err\n");
break;
}
if (SOCKET_ERROR == setsockopt(soc, SOL_SOCKET, SO_RCVTIMEO, (char*)&nTimeOut, sizeof(nTimeOut)))
{
err = GetLastError();
DebugPrintA("set rcvtime out err\n");
break;
}
struct sockaddr_in addrSrv;
addrSrv.sin_addr.S_un.S_addr = IP;
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(123);//123
NTP_Packet NTP_Send, NTP_Recv;
NTP_Send.Control_Word = htonl(0x0B000000);
NTP_Send.root_delay = 0;
NTP_Send.root_dispersion = 0;
NTP_Send.reference_identifier = 0;
NTP_Send.reference_timestamp = 0;
NTP_Send.originate_timestamp = 0;
NTP_Send.receive_timestamp = 0;
NTP_Send.transmit_timestamp_seconds = 0;
NTP_Send.transmit_timestamp_fractions = 0;
if (SOCKET_ERROR == sendto(soc, (const char*)&NTP_Send, sizeof(NTP_Send), 0, (struct sockaddr*)&addrSrv, sizeof(addrSrv)))
{
err = GetLastError();
DebugPrintA("set send err\n");
break;
}
printf("send ok\n");
int sockaddr_Size = sizeof(addrSrv);
if (SOCKET_ERROR == recvfrom(soc, (char*)&NTP_Recv, sizeof(NTP_Recv), 0, (struct sockaddr*)&addrSrv, &sockaddr_Size))
{
err = GetLastError();
DebugPrintA("set rcv err\n");
break;
}
// 获取时间服务器的时间
time_t ntp_time = ntohl(NTP_Recv.transmit_timestamp_seconds) - 2208988800;
struct tm * lpLocalTime = localtime(&ntp_time);
if (lpLocalTime == NULL)
{
err = GetLastError();
printf("localtime err\n");
break;;
}
// 获取新的时间
SYSTEMTIME newtime;
newtime.wYear = lpLocalTime->tm_year + 1900;
newtime.wMonth = lpLocalTime->tm_mon + 1;
newtime.wDayOfWeek = lpLocalTime->tm_wday;
newtime.wDay = lpLocalTime->tm_mday;
newtime.wHour = lpLocalTime->tm_hour;
newtime.wMinute = lpLocalTime->tm_min;
newtime.wSecond = lpLocalTime->tm_sec;
DebugPrintA("%d-%d-%d %d:%d:%d\n", newtime.wYear, newtime.wMonth, newtime.wDay, newtime.wHour, newtime.wMinute, newtime.wSecond);
// 设置时间精度
float Splitseconds = (float)ntohl(NTP_Recv.transmit_timestamp_fractions);
Splitseconds = (float)0.000000000200 * Splitseconds;
Splitseconds = (float)1000.0 * Splitseconds;
newtime.wMilliseconds = (unsigned short)Splitseconds;
// 修改本机系统时间
if (!SetLocalTime(&newtime))
{
err = GetLastError();
DebugPrintA("SetLocalTime err\n");
break;
}
} while (0);
if (soc != NULL)
{
closesocket(soc);
soc = NULL;
}
return err;
}
ULONG DNS(char* pHostName,ULONG& err)
{
ULONG ServerIP = 0;
hostent *host = gethostbyname(pHostName);
err = GetLastError();
DebugPrintA("gethostbyname%s 0x%x\n", pHostName, err);
for (int i = 0; host != NULL; i++)
{
in_addr *p = (in_addr*)host->h_addr_list[i];
if (p == NULL)
{
DebugPrintA("no valid host data\n");
break;
}
ServerIP = p->S_un.S_addr;
DebugPrintA("%d.%d.%d.%d\n", p->S_un.S_un_b.s_b1, p->S_un.S_un_b.s_b2, p->S_un.S_un_b.s_b3, p->S_un.S_un_b.s_b4);
if (ServerIP != 0)
{
break;
}
}
return ServerIP;
}
#include <winsvc.h>
DWORD CUtils::RestartSerivce(TCHAR* pSeriveName)
{
DWORD err = STATUS_SUCCESS;
SC_HANDLE hSC = NULL;
SC_HANDLE hSvc = NULL;
do
{
// 打开服务管理对象
hSC = ::OpenSCManager(NULL, NULL, GENERIC_EXECUTE);
if (hSC == NULL)
{
err = GetLastError();
DebugPrintA("OpenSCManager err %x\n", err);
break;
}
// 打开www服务。
SC_HANDLE hSvc = ::OpenService(hSC, pSeriveName, SERVICE_START | SERVICE_QUERY_STATUS | SERVICE_STOP | SERVICE_ENUMERATE_DEPENDENTS);
if (hSvc == NULL)
{
err = GetLastError();
DebugPrintA("OpenService err %x\n", err);
::CloseServiceHandle(hSC);
break;
}
// 获得服务的状态
SERVICE_STATUS status;
if (::QueryServiceStatus(hSvc, &status) == FALSE)
{
err = GetLastError();
DebugPrintA("QueryServiceStatus err %x\n", err);
break;
}
//如果处于运行态,则停止服务
if (status.dwCurrentState == SERVICE_RUNNING)
{
//停止依赖者
{
DWORD dwBytesNeeded = 0;
DWORD dwCount = 0;
ENUM_SERVICE_STATUS ess;
SC_HANDLE hDepService;
LPENUM_SERVICE_STATUS lpDependencies = NULL;
if (EnumDependentServices(hSvc, SERVICE_ACTIVE, lpDependencies, 0, &dwBytesNeeded, &dwCount))
{
err = GetLastError();
DebugPrintA("EnumDependentServices err %x\n", err);
break;
}
if (GetLastError() != ERROR_MORE_DATA)
{
err = GetLastError();
break;
}
// Allocate a buffer for the dependencies
lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded);
if (!lpDependencies)
{
err = GetLastError();
DebugPrintA("HeapAlloc err %x\n", err);
break;
}
__try
{
// Enumerate the dependencies
if (!EnumDependentServices(hSvc, SERVICE_ACTIVE, lpDependencies, dwBytesNeeded, &dwBytesNeeded, &dwCount))
{
err = GetLastError();
DebugPrintA("EnumDependentServices err %x\n", err);
break;
}
for (DWORD i = 0; i < dwCount; i++)
{
ess = *(lpDependencies + i);
DebugPrintW(TEXT("SubServer:%s\n"), ess.lpServiceName);
// Open the service
hDepService = OpenService(hSC, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS);
if (!hDepService)
{
err = GetLastError();
DebugPrintA("OpenService2 err %x\n", err);
break;
}
__try
{
SERVICE_STATUS ss;
if (!ControlService(hDepService, SERVICE_CONTROL_STOP, &ss))
{
err = GetLastError();
DebugPrintA("ControlService2 err %x\n", err);
break;
}
// Wait for the service to stop
while (ss.dwCurrentState != SERVICE_STOPPED)
{
Sleep(3000);
if (!QueryServiceStatus(hDepService, &ss))
{
err = GetLastError();
DebugPrintA("QueryServiceStatus2 err %x\n", err);
break;
}
if (ss.dwCurrentState == SERVICE_STOPPED)
{
DebugPrintA("SubServer%d/%d SERVICE_STOPPED\n", i, dwCount);
break;
}
else
{
DebugPrintA("Wait SubServer%d/%d stopeend\n", i, dwCount);
}
}
}
__finally
{
CloseServiceHandle(hDepService);
}
}
}
__finally
{
// Always free the enumeration buffer
if (lpDependencies != NULL)
{
HeapFree(GetProcessHeap(), 0, lpDependencies);
lpDependencies = NULL;
}
}
}
if (!ControlService(hSvc, SERVICE_CONTROL_STOP, &status))
{
err = GetLastError();
DebugPrintA("ControlService err %x\n", err);
break;
}
// 等待服务停止
while (::QueryServiceStatus(hSvc, &status) == TRUE)
{
// ::Sleep(status.dwWaitHint);
Sleep(3000);
if (status.dwCurrentState == SERVICE_STOPPED)
{
DebugPrintA("SERVICE_CONTROL_STOP ok\n");
break;
}
else
{
DebugPrintA("Wait SERVICE_CONTROL_STOP\n");
}
}
}
// 启动服务
if (::StartService(hSvc, NULL, NULL) == FALSE)
{
err = GetLastError();
DebugPrintA("ControlService err %x\n", err);
break;
}
// 等待服务启动
while (::QueryServiceStatus(hSvc, &status) == TRUE)
{
::Sleep(status.dwWaitHint);
if (status.dwCurrentState == SERVICE_RUNNING)
{
DebugPrintA("SERVICE_RUNNING ok\n");
break;
}
else
{
DebugPrintA("Wait SERVICE_RUNNING\n");
}
}
} while (0);
if (hSvc != NULL)
{
::CloseServiceHandle(hSvc);
}
if (hSC != NULL)
{
::CloseServiceHandle(hSC);
}
DebugPrintA("Restart Servuce %x\n", err);
return err;
}
BOOL CUtils::SaveBuffToFile(PCHAR pFileName, PVOID pBuff, ULONG len)
{
FILE* fp = NULL;
fopen_s(&fp,pFileName, "wb");
if (fp == NULL)
{
return FALSE;
}
fwrite(pBuff, len, 1, fp);
fclose(fp);
return TRUE;
}
BOOL CUtils::GetBufferFromFile(TCHAR* pFileName, std::string& strFileStream)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
BOOL isok = FALSE;
do
{
hFile = CreateFile(pFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
break;
}
DWORD dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == 0)
{
break;
}
strFileStream.resize(dwFileSize);
DWORD dwBytesRead = 0;
isok = ReadFile(hFile, (PVOID)&strFileStream.at(0), dwFileSize, &dwBytesRead, NULL);
if (!isok)
{
break;
}
} while (0);
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
}
return isok;
}
#pragma warning(disable:4267)
BOOL CUtils::CharToWchar(std::string src, std::wstring& dest)
{
int dwMinSize = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src.c_str(), -1, NULL, 0);
if (dwMinSize == 0)
{
return 0;
}
dest.resize(dwMinSize);
int nlen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src.c_str(), -1, &dest.at(0), dwMinSize);
return nlen > 0;
}
BOOL CUtils::WcharToChar(std::wstring src, std::string& dest)
{
int dwMinSize = WideCharToMultiByte(CP_ACP, NULL, src.c_str(), -1, NULL, 0, NULL, FALSE);
if (dwMinSize == 0)
{
return 0;
}
dest.resize(dwMinSize);
int nlen = WideCharToMultiByte(CP_ACP, NULL, src.c_str(), -1, &dest.at(0), dwMinSize, NULL, FALSE);
return nlen > 0;
}
BOOL CUtils::UTF8ToWchar(std::string src, std::wstring& dest)
{
//预转换,得到所需空间的大小;
int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, src.c_str(), src.size(), NULL, 0);
if (wcsLen == 0)
{
return 0;
}
dest.resize(wcsLen);
int nLen = ::MultiByteToWideChar(CP_UTF8, NULL, src.c_str(),src.size(), &dest.at(0), wcsLen);
return wcsLen > 0;
}
BOOL CUtils::WcharToUTF8(std::wstring src, std::string& dest)
{
int dwMinSize = WideCharToMultiByte(CP_UTF8, NULL, src.c_str(), -1, NULL, 0, NULL, FALSE);
if (dwMinSize == 0)
{
return 0;
}
dest.resize(dwMinSize);
int nLen = WideCharToMultiByte(CP_UTF8, 0, src.c_str(), -1, &dest.at(0), dwMinSize, NULL, NULL);
return nLen > 0;
}
#pragma warning(default:4267)
读写注册表函数封装,使用方法可参见:https://www.trcp.net/article/detail-29.html
DWORD CUtils::SetRegisterValue(HKEY key, LPCSTR path, LPCSTR name, LPBYTE pData, ULONG nLen, DWORD type)
{
HKEY hKey = NULL;
DWORD err = STATUS_SUCCESS;
do
{
#ifndef _WIN64
long lRet = RegCreateKeyExA(key, (LPCSTR)path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, &hKey, NULL);
#else
long lRet = RegCreateKeyExA(key, (LPCSTR)path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS , NULL, &hKey, NULL);
#endif
if (ERROR_SUCCESS != lRet)
{
err = GetLastError();
DebugPrintA("RegCreateKeyExA error[%d,%D]\n", err, lRet);
break;
}
lRet = RegSetValueExA(hKey, name, 0, type, pData, nLen);
if (ERROR_SUCCESS != lRet)
{
err = GetLastError();
DebugPrintA("RegSetValueExA error[%d]\n", err);
break;
}
} while (0);
if (hKey)
{
RegCloseKey(hKey);
}
return err;
}
BOOL CUtils::GetRegisterValue(HKEY key, LPCSTR path, LPCSTR name, std::string& strAccessStream)
{
HKEY hKey = NULL;
bool bIsok = false;
do
{
#ifndef _WIN64
long lRet = RegCreateKeyExA(key, (LPCSTR)path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WOW64_64KEY, NULL, &hKey, NULL);
#else
long lRet = RegCreateKeyExA(key, (LPCSTR)path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ , NULL, &hKey, NULL);
#endif
if (ERROR_SUCCESS != lRet)
{
DebugPrintA("RegCreateKeyExA=%d", GetLastError());
break;
}
DWORD len = 0;
lRet = RegQueryValueExA(hKey, name, 0, NULL, NULL, &len);
if (ERROR_SUCCESS != lRet)
{
DebugPrintA("RegQueryValueExA=%d", lRet);
break;
}
if (len == 0)
{
DebugPrintA("RegQueryValueExA datalen=%d", len);
break;
}
strAccessStream.resize(len);
BYTE* pData = (BYTE*)&strAccessStream.at(0);
lRet = RegQueryValueExA(hKey, name, 0, NULL, pData, &len);
if (ERROR_SUCCESS != lRet)
{
DebugPrintA("RegQueryValueExA=%d", lRet);
break;
}
bIsok = true;
} while (0);
if (hKey)
{
RegCloseKey(hKey);
}
return bIsok;
}
int CUtils::hex(char ch)
{
if (ch >= 'A' && ch <= 'F')
{
return ch - 'A' + 10;
}
else if (ch >= 'a' && ch <= 'f')
{
return ch - 'a' + 10;
}
else if (ch >= '0' && ch <= '9')
{
return ch - '0';
}
return 0;
}
实现自动登录需要登录的用户名和密码。
SetRegisterKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", L"AutoAdminLogon", L"1");
SetRegisterKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", L"DefaultUserName", strName);
SetRegisterKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", L"DefaultPassword", pPassword);
禁用Windows自动登录只需要更改注册表即可:
SetRegisterKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", L"AutoAdminLogon", L"0");
SetRegisterKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", L"DefaultUserName", L"");
SetRegisterKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", L"DefaultPassword", L"");
当然,对注册表的修改由于是HKEY_LOCAL_MACHINE,所以必须是管理员权限。
