PCIE MSI-X

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。

2024-04-30 16:51:18
GNU C语言结构体的部分初始化

学习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)
2023-10-07 10:46:22
LINUX 大小端字节序宏

在查看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
2023-10-07 10:45:34
IF条件判断的思考

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就是了,那么再判断是不是音频流端点是否启用。这种代码的思路看着是不是着着更清晰一点,也好像弥补了我们第一种思路代码写完后的有点失落感。

2023-10-07 10:45:00
删除文件夹(Windows API封装)
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;
}
2023-09-28 12:09:31
HTTP请求(Windows API封装)

#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;
}
2023-09-28 12:08:04
强制同步系统时间(Windows API封装)

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;
}
2023-09-28 12:06:46
解析域名到IP(Windows API封装)
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;
}
2023-09-28 12:05:31
重启服务及其依赖服务(Windows API封装)

#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;
}
2023-09-28 11:59:25
文件转内存和内存转存文件(Windows API封装)


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;
}
2023-09-28 11:58:33
字符串转换(多字节转换宽字节、UTF-8)(Windows API封装)
#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)
2023-09-28 11:57:26
读写注册表(Windows API封装)

读写注册表函数封装,使用方法可参见: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;
}
2023-09-28 11:56:18
字符转十六进制(Windows API封装)
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;
}
2023-09-28 11:45:30
修改注册表实现Windows自动登录(Windows API封装)

实现自动登录需要登录的用户名和密码。

    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);
2023-09-28 10:38:05
禁用Windows自动登录(Windows API封装)

禁用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,所以必须是管理员权限。

2023-09-28 10:36:18

站内合集

关注公众号
关注本站公众号,获取更多编程资源、学习建议、优质文章、最新动态