当前位置: 首页>>代码示例>>C++>>正文


C++ CAutoFile::CloseHandle方法代码示例

本文整理汇总了C++中CAutoFile::CloseHandle方法的典型用法代码示例。如果您正苦于以下问题:C++ CAutoFile::CloseHandle方法的具体用法?C++ CAutoFile::CloseHandle怎么用?C++ CAutoFile::CloseHandle使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在CAutoFile的用法示例。


在下文中一共展示了CAutoFile::CloseHandle方法的6个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: sizeof

TEST(UpdateCrypto, Binary)
{
	CAutoTempDir tempdir;
	CString testFile = tempdir.GetTempDir() + L"\\test.bin";

	unsigned char binaryFile[99] = // based on link.png
	{
		0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
		0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00, 0xFE, 0xC1, 0x2C,
		0xC8, 0x00, 0x00, 0x00, 0x06, 0x50, 0x4C, 0x54, 0x45, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xA5,
		0xD9, 0x9F, 0xDD, 0x00, 0x00, 0x00, 0x18, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5E, 0x63, 0xF8, 0xC0,
		0xF0, 0x87, 0xE1, 0x17, 0x83, 0x18, 0x43, 0x3E, 0x43, 0x38, 0x43, 0x39, 0x03, 0x3B, 0x00, 0x2C,
		0x98, 0x04, 0x41, 0xFA, 0xEC, 0xE7, 0x75, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE,
		0x42, 0x60, 0x82,
	};

	CAutoFile file = ::CreateFile(testFile, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
	ASSERT_TRUE(file.IsValid());
	DWORD written = 0;
	EXPECT_TRUE(::WriteFile(file, binaryFile, sizeof(binaryFile), &written, nullptr));
	EXPECT_EQ(sizeof(binaryFile), written);
	EXPECT_TRUE(file.CloseHandle());

	CString testFileSignature = testFile + _T(".rsa.asc");
	EXPECT_TRUE(CStringUtils::WriteStringToTextFile((LPCTSTR)testFileSignature, L"-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v2\n\niQIcBAABCgAGBQJVxPvgAAoJEPfxez+d2VOerKsP/iQlt4S20LdUknT5udD8fFpT\nEFhZDPTXMRWkd8OhCLxa+t5b/ijyxFKWNz808Q7BDQcQoOQtC19NDvVmAcfqXflt\nR4Z+ugCG/lqP+3y0xBrL9m4UT9fNzQCiUY8Xpaih+6riLGnXVVpUe29BgVZppEWn\nMG9RVXpXwC+M3VQ0yQWu1F2Yy5OjdH4Ww5kpluoseZMOPhT6VaSfXeyQmg2DrBbw\nUfVV+w718noZ5znDH9MiD5y+sd4o7vqN2YFdg6FNvTjHyha39aFV8UCpPX1lH9ME\nN9v1vt5IWGCWL0zsZ6umHqibGG3Q2S3mlqktFhKJGWci+Swy4cNMpXDHIKY6e5v7\nxPIP92djyFtbjdixcSqBaYFC/Dd0KuCa1eYmyi2KxzUP29rZ+EHWoazfbeL1Y2Pu\nkSBrVFv64j0URzSMxUpJMqYXZRC5QW7vdbVwHGAPzoS+0rBBddwfSKteBQjagcHA\nkLk3sAIZNj1JaP5dcGL2K4Wxlaae0WgwI48lZSBMoL8SaInQvcKq9iL64xfpU+FU\nG0mzbidvTfZpyEU3eeSNiFi+6z4XLQ3NUFxsOr5jEPVKvgRoPljhJ4nCx034KQRQ\nHbVF9KYgMJSroKN9bNi/UFkC45Pc4wVov/XyH82XCVS30Du4hsVXsTdAiiXb3i6w\nkrWIJWYRxx76XGtQoHrR\n=PlFQ\n-----END PGP SIGNATURE-----"));
	EXPECT_EQ(0, VerifyIntegrity(testFile, testFileSignature, nullptr));

	// signature is shorter than pubkey; did not work w/o commit 941c103c00e48b0ffe592ab4d87d40ff48f899f6
	EXPECT_TRUE(CStringUtils::WriteStringToTextFile((LPCTSTR)testFileSignature, L"-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v2\n\niQIbBAABCgAGBQJVxQQOAAoJEPfxez+d2VOe7GoP+KflvYJVpNXSwnteXyDc1zTo\nJAyAJFtW6mgqCLrN6KoMrncEvd0cHrD07hT5mxULkbP6zy9fGaFYF0gHO0mOqErF\nIIbDcpPTWooJWUHMbnuQjf2I0x70Cr8ikycZQ7uDg7scZx7E8EIwHOJX60dcfdVX\nK1SQ+c+VIvo1uxL1PndloACaeINz6rL0Pj504lVDJaaGBvzdAV6KEIcjjm+Jb4r0\n6CYEntmt1i3Mc8FM6Xp1QfGtJqp4ogjv6o89hvtaBBLihB54EVQn66/2qIjdhX8W\nkdqJE6+pmFTfuD02XNECwl6stDIZcxXCw6EE87/1hdHip8oW9enIVTxKWB3fUWHl\n236eE2qb8zAN/WWGx/2Cvi6ctyosy9Cc/1hopnmV0KgZFfmDJWw0lISlC/3ZYWEe\nQFiXs5FPzLwfKnkq4REpoOKKfbZNk329J2iLFnwrF0mlL4vUZ1m26BBBk6lhm41J\nnjOSFWhJG/AqBbR5DqdJfXMqnxpfVZfaE5cry2rhjI4mfzw0xzrgvL4M9FZ7R9F8\njVHAV11CMqtp/7gMHXu6ljkTEBBQ7cgbU5DEAwfWddaJF+R30jmNSVliN2JW2FAk\nIbE8yV+uPiyXebn49CmRzkOWOAZqx+DShqriXGam37qjhdys147wPMMiwk8lZKjP\n4V66gTFw45UvBpophyg=\n=0bmW\n-----END PGP SIGNATURE-----"));
	EXPECT_EQ(0, VerifyIntegrity(testFile, testFileSignature, nullptr));
}
开发者ID:AJH16,项目名称:TortoiseGit,代码行数:31,代码来源:UpdateCryptoTest.cpp

示例2: InternalEnsurePipeOpen

bool CRemoteCacheLink::InternalEnsurePipeOpen ( CAutoFile& hPipe
											  , const CString& pipeName) const
{
	if (hPipe)
		return true;

	int tryleft = 2;

	while (!hPipe && tryleft--)
	{

		hPipe = CreateFile(
							pipeName,                       // pipe name
							GENERIC_READ |                  // read and write access
							GENERIC_WRITE,
							0,                              // no sharing
							NULL,                           // default security attributes
							OPEN_EXISTING,                  // opens existing pipe
							FILE_FLAG_OVERLAPPED,           // default attributes
							NULL);                          // no template file
		if ((!hPipe) && (GetLastError() == ERROR_PIPE_BUSY))
		{
			// TGitCache is running but is busy connecting a different client.
			// Do not give up immediately but wait for a few milliseconds until
			// the server has created the next pipe instance
			if (!WaitNamedPipe (pipeName, 50))
			{
				continue;
			}
		}
	}

	if (hPipe)
	{
		// The pipe connected; change to message-read mode.
		DWORD dwMode;

		dwMode = PIPE_READMODE_MESSAGE;
		if(!SetNamedPipeHandleState(
			hPipe,    // pipe handle
			&dwMode,  // new pipe mode
			NULL,     // don't set maximum bytes
			NULL))    // don't set maximum time
		{
			CTraceToOutputDebugString::Instance()(__FUNCTION__ ": SetNamedPipeHandleState failed");
			hPipe.CloseHandle();
		}
	}

	return hPipe;
}
开发者ID:hongzuL,项目名称:TortoiseGit,代码行数:51,代码来源:RemoteCacheLink.cpp

示例3: Execute


//.........这里部分代码省略.........

            CSimpleIni::TNamesDepend mitems;
            regexIni.GetAllSections(mitems);
            for (const auto& mitem : mitems)
            {
                CString sSection = mitem;

                CString newval = regexIni.GetValue(mitem, L"regex", L"");
                CString oldval = iniFile.GetValue(L"ini_tmergeregex", sSection + L".regex", L"");
                bHaveChanges |= newval != oldval;
                iniFile.SetValue(L"ini_tmergeregex", sSection + L".regex", newval);

                newval = regexIni.GetValue(mitem, L"replace", L"5");
                oldval = iniFile.GetValue(L"ini_tmergeregex", sSection + L".replace", L"0");
                bHaveChanges |= newval != oldval;
                iniFile.SetValue(L"ini_tmergeregex", sSection + L".replace", newval);
            }
        }
    }


    if (bHaveChanges)
    {
        iniFile.SetValue(L"sync", L"version", TSVN_SYNC_VERSION_STR);
        DWORD count = regCount;
        ++count;
        regCount = count;
        CString tmp;
        tmp.Format(L"%lu", count);
        iniFile.SetValue(L"sync", L"synccounter", tmp);

        // save the ini file
        std::string iniData;
        iniFile.SaveString(iniData);
        iniData = "***" + iniData;
        // encrypt the string

        CString password;
        if (parser.HasKey(L"askforpath"))
        {
            CPasswordDlg passDlg(CWnd::FromHandle(GetExplorerHWND()));
            passDlg.m_bForSave = true;
            if (passDlg.DoModal() != IDOK)
                return false;
            password = passDlg.m_sPW1;
        }
        else
        {
            CRegString regPW(L"Software\\TortoiseSVN\\SyncPW");
            auto passwordbuf = CStringUtils::Decrypt(CString(regPW));
            if (passwordbuf.get())
            {
                password = passwordbuf.get();
            }
        }

        std::string passworda = CUnicodeUtils::StdGetUTF8((LPCWSTR)password);

        std::string encrypted = CStringUtils::Encrypt(iniData, passworda);
        CPathUtils::MakeSureDirectoryPathExists(syncPath.GetContainingDirectory().GetWinPathString());
        CString sTempfile = CTempFiles::Instance().GetTempFilePathString();
        CAutoFile hFile = CreateFile(sTempfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile.IsValid())
        {
            DWORD written = 0;
            if (WriteFile(hFile, encrypted.c_str(), DWORD(encrypted.size()), &written, NULL))
            {
                if (hFile.CloseHandle())
                {
                    if (!CopyFile(sTempfile, syncPath.GetWinPath(), FALSE))
                    {
                        CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error copying %s to %s, Error: %u\n", (LPCWSTR)sTempfile, syncPath.GetWinPath(), GetLastError());
                    }
                    else
                        bRet = true;
                }
                else
                    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error closing file %s, Error: %u\n", (LPCWSTR)sTempfile, GetLastError());
            }
            else
                CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error writing to file %s, Error: %u\n", (LPCWSTR)sTempfile, GetLastError());
        }
        else
            CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error creating file %s for writing, Error: %u\n", (LPCWSTR)sTempfile, GetLastError());

        if (bSyncAuth)
        {
            // now save all auth data
            CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth");
            CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.simple");
            CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.ssl.client-passphrase");
            CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.ssl.server");
            CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.username");
            authData.ExportAuthData(syncFolder.GetWinPathString(), password);
        }
    }


    return bRet;
}
开发者ID:TortoiseGit,项目名称:tortoisesvn,代码行数:101,代码来源:SyncCommand.cpp

示例4: CommandWaitThread

DWORD WINAPI CommandWaitThread(LPVOID lpvParam)
{
	ATLTRACE("CommandWaitThread started\n");
	bool * bRun = (bool *)lpvParam;
	// The main loop creates an instance of the named pipe and
	// then waits for a client to connect to it. When the client
	// connects, a thread is created to handle communications
	// with that client, and the loop is repeated.
	DWORD dwThreadId;
	BOOL fConnected;
	CAutoFile hPipe;

	while (*bRun)
	{
		hPipe = CreateNamedPipe(
			GetCacheCommandPipeName(),
			PIPE_ACCESS_DUPLEX,       // read/write access
			PIPE_TYPE_MESSAGE |       // message type pipe
			PIPE_READMODE_MESSAGE |   // message-read mode
			PIPE_WAIT,                // blocking mode
			PIPE_UNLIMITED_INSTANCES, // max. instances
			BUFSIZE,                  // output buffer size
			BUFSIZE,                  // input buffer size
			NMPWAIT_USE_DEFAULT_WAIT, // client time-out
			NULL);                // NULL DACL

		if (!hPipe)
		{
			//OutputDebugStringA("TSVNCache: CreatePipe failed\n");
			//DebugOutputLastError();
			if (*bRun)
				Sleep(200);
			continue; // never leave the thread!
		}

		// Wait for the client to connect; if it succeeds,
		// the function returns a nonzero value. If the function returns
		// zero, GetLastError returns ERROR_PIPE_CONNECTED.
		fConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
		if (fConnected)
		{
			// Create a thread for this client.
			CAutoGeneralHandle hCommandThread = CreateThread(
				NULL,              // no security attribute
				0,                 // default stack size
				CommandThread,
				(HANDLE) hPipe,    // thread parameter
				0,                 // not suspended
				&dwThreadId);      // returns thread ID

			if (!hCommandThread)
			{
				//OutputDebugStringA("TSVNCache: Could not create Command thread\n");
				//DebugOutputLastError();
				DisconnectNamedPipe(hPipe);
				hPipe.CloseHandle();
				// since we're now closing this thread, we also have to close the whole application!
				// otherwise the thread is dead, but the app is still running, refusing new instances
				// but no pipe will be available anymore.
				PostMessage(hWnd, WM_CLOSE, 0, 0);
				return 1;
			}
			// detach the handle, since we passed it to the thread
			hPipe.Detach();
		}
		else
		{
			// The client could not connect, so close the pipe.
			//OutputDebugStringA("TSVNCache: ConnectNamedPipe failed\n");
			//DebugOutputLastError();
			hPipe.CloseHandle();
			if (*bRun)
				Sleep(200);
			continue;	// don't end the thread!
		}
	}
	ATLTRACE("CommandWait thread exited\n");
	return 0;
}
开发者ID:chengn,项目名称:TortoiseGit,代码行数:79,代码来源:TGITCache.cpp

示例5: Load

bool CPicture::Load(tstring sFilePathName)
{
	bool bResult = false;
	bIsIcon = false;
	lpIcons = NULL;
	//CFile PictureFile;
	//CFileException e;
	FreePictureData(); // Important - Avoid Leaks...

	// No-op if no file specified
	if (sFilePathName.empty())
		return true;

	// Load & initialize the GDI+ library if available
	HMODULE hGdiPlusLib = AtlLoadSystemLibraryUsingFullPath(_T("gdiplus.dll"));
	if (hGdiPlusLib && GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) == Ok)
	{
		bHaveGDIPlus = true;
	}
	// Since we loaded the gdiplus.dll only to check if it's available, we
	// can safely free the library here again - GdiplusStartup() loaded it too
	// and reference counting will make sure that it stays loaded until GdiplusShutdown()
	// is called.
	FreeLibrary(hGdiPlusLib);

	// Attempt to load using GDI+ if available
	if (bHaveGDIPlus)
	{
		pBitmap = new Bitmap(sFilePathName.c_str(), FALSE);
		GUID guid;
		pBitmap->GetRawFormat(&guid);

		if (pBitmap->GetLastStatus() != Ok)
		{
			delete pBitmap;
			pBitmap = NULL;
		}

		// gdiplus only loads the first icon found in an icon file
		// so we have to handle icon files ourselves :(

		// Even though gdiplus can load icons, it can't load the new
		// icons from Vista - in Vista, the icon format changed slightly.
		// But the LoadIcon/LoadImage API still can load those icons,
		// at least those dimensions which are also used on pre-Vista
		// systems.
		// For that reason, we don't rely on gdiplus telling us if
		// the image format is "icon" or not, we also check the
		// file extension for ".ico".
		std::transform(sFilePathName.begin(), sFilePathName.end(), sFilePathName.begin(), ::tolower);
		bIsIcon = (guid == ImageFormatIcon) || (wcsstr(sFilePathName.c_str(), L".ico") != NULL) || (wcsstr(sFilePathName.c_str(), L".cur") != NULL);
		bIsTiff = (guid == ImageFormatTIFF) || (_tcsstr(sFilePathName.c_str(), _T(".tiff")) != NULL);
		m_Name = sFilePathName;

		if (bIsIcon)
		{
			// Icon file, get special treatment...
			if (pBitmap)
			{
				// Cleanup first...
				delete (pBitmap);
				pBitmap = NULL;
				bIsIcon = true;
			}

			CAutoFile hFile = CreateFile(sFilePathName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
			if (hFile)
			{
				BY_HANDLE_FILE_INFORMATION fileinfo;
				if (GetFileInformationByHandle(hFile, &fileinfo))
				{
					lpIcons = new BYTE[fileinfo.nFileSizeLow];
					DWORD readbytes;
					if (ReadFile(hFile, lpIcons, fileinfo.nFileSizeLow, &readbytes, NULL))
					{
						// we have the icon. Now gather the information we need later
						if (readbytes >= sizeof(ICONDIR))
						{
							// we are going to open same file second time so we have to close the file now
							hFile.CloseHandle();

							LPICONDIR lpIconDir = (LPICONDIR)lpIcons;
							if ((lpIconDir->idCount) && ((lpIconDir->idCount * sizeof(ICONDIR)) <= fileinfo.nFileSizeLow))
							{
								try
								{
									bResult = false;
									nCurrentIcon = 0;
									hIcons = new HICON[lpIconDir->idCount];
									// check that the pointers point to data that we just loaded
									if (((BYTE*)lpIconDir->idEntries > (BYTE*)lpIconDir) && 
										(((BYTE*)lpIconDir->idEntries) + (lpIconDir->idCount * sizeof(ICONDIRENTRY)) < ((BYTE*)lpIconDir) + fileinfo.nFileSizeLow))
									{
										m_Width = lpIconDir->idEntries[0].bWidth;
										m_Height = lpIconDir->idEntries[0].bHeight;
										bResult = true;
										for (int i=0; i<lpIconDir->idCount; ++i)
										{
											hIcons[i] = (HICON)LoadImage(NULL, sFilePathName.c_str(), IMAGE_ICON,
																		 lpIconDir->idEntries[i].bWidth,
//.........这里部分代码省略.........
开发者ID:15375514460,项目名称:TortoiseGit,代码行数:101,代码来源:Picture.cpp

示例6: Load

BOOL CFileTextLines::Load(const CString& sFilePath, int lengthHint /* = 0*/)
{
	m_LineEndings = EOL_AUTOLINE;
	m_UnicodeType = CFileTextLines::AUTOTYPE;
	RemoveAll();
	m_endings.clear();
	if(lengthHint != 0)
	{
		Reserve(lengthHint);
	}

	if (PathIsDirectory(sFilePath))
	{
		m_sErrorString.Format(IDS_ERR_FILE_NOTAFILE, (LPCTSTR)sFilePath);
		return FALSE;
	}

	if (!PathFileExists(sFilePath))
	{
		//file does not exist, so just return SUCCESS
		return TRUE;
	}

	CAutoFile hFile = CreateFile(sFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
	if (!hFile)
	{
		SetErrorString();
		return FALSE;
	}

	LARGE_INTEGER fsize;
	if (!GetFileSizeEx(hFile, &fsize))
	{
		SetErrorString();
		return false;
	}
	if (fsize.HighPart)
	{
		// file is way too big for us
		m_sErrorString.LoadString(IDS_ERR_FILE_TOOBIG);
		return FALSE;
	}

	// If new[] was done for type T delete[] must be called on a pointer of type T*,
	// otherwise the behavior is undefined.
	// +1 is to address possible truncation when integer division is done
	wchar_t* pFileBuf = new wchar_t[fsize.LowPart/sizeof(wchar_t) + 1];
	DWORD dwReadBytes = 0;
	if (!ReadFile(hFile, pFileBuf, fsize.LowPart, &dwReadBytes, NULL))
	{
		delete [] pFileBuf;
		SetErrorString();
		return FALSE;
	}
	if (m_UnicodeType == CFileTextLines::AUTOTYPE)
	{
		m_UnicodeType = this->CheckUnicodeType(pFileBuf, dwReadBytes);
	}
	if (m_LineEndings == EOL_AUTOLINE)
	{
		m_LineEndings = CheckLineEndings(pFileBuf, min(10000, dwReadBytes));
	}
	hFile.CloseHandle();

	if (m_UnicodeType == CFileTextLines::BINARY)
	{
		m_sErrorString.Format(IDS_ERR_FILE_BINARY, (LPCTSTR)sFilePath);
		delete [] pFileBuf;
		return FALSE;
	}

	// we may have to convert the file content
	if ((m_UnicodeType == UTF8)||(m_UnicodeType == UTF8BOM))
	{
		int ret = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pFileBuf, dwReadBytes, NULL, 0);
		wchar_t * pWideBuf = new wchar_t[ret];
		int ret2 = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pFileBuf, dwReadBytes, pWideBuf, ret);
		if (ret2 == ret)
		{
			delete [] pFileBuf;
			pFileBuf = pWideBuf;
			dwReadBytes = ret2;
		} else
			delete [] pWideBuf;
	}
	else if (m_UnicodeType == ASCII)
	{
		int ret = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)pFileBuf, dwReadBytes, NULL, 0);
		wchar_t * pWideBuf = new wchar_t[ret];
		int ret2 = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)pFileBuf, dwReadBytes, pWideBuf, ret);
		if (ret2 == ret)
		{
			delete [] pFileBuf;
			pFileBuf = pWideBuf;
			dwReadBytes = ret2;
		}
		else
			delete [] pWideBuf;
	}
	// fill in the lines into the array
//.........这里部分代码省略.........
开发者ID:goodoid,项目名称:TortoiseGit,代码行数:101,代码来源:FileTextLines.cpp


注:本文中的CAutoFile::CloseHandle方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。