BCryptGenRandom_PinnedBuffer() static private method

static private BCryptGenRandom_PinnedBuffer ( byte pbBuffer, int obBuffer, int cbBuffer ) : NTSTATUS
pbBuffer byte
obBuffer int
cbBuffer int
return NTSTATUS
		}//NextBytes()

		void NextBytesInternal(ArraySegment<byte> bufferSegment)
		{
			BCrypt.NTSTATUS status;
			var buffer = bufferSegment.Array;
			var offset = bufferSegment.Offset;
			var count = bufferSegment.Count;

			if (count > CACHE_THRESHOLD)
			{
				status = (offset == 0) ? BCrypt.BCryptGenRandom(buffer, count) : BCrypt.BCryptGenRandom_PinnedBuffer(buffer, offset, count);
				if (status == BCrypt.NTSTATUS.STATUS_SUCCESS) return;
				throw new CryptographicException((int)status);
			}

			lock (_byteCache)
			{
				if (_byteCachePosition + count <= BYTE_CACHE_SIZE)
				{
					Utils.BlockCopy(_byteCache, _byteCachePosition, buffer, offset, count);
					_byteCachePosition += count;
					return;
				}

				status = BCrypt.BCryptGenRandom(_byteCache, BYTE_CACHE_SIZE);
				if (status == BCrypt.NTSTATUS.STATUS_SUCCESS)
				{
					_byteCachePosition = count;
					Utils.BlockCopy(_byteCache, 0, buffer, offset, count);
					return;
				}
				throw new CryptographicException((int)status);
			}// lock
		}//NextBytesInternal()
		void NextBytesInternal(ArraySegment<byte> bufferSegment)
		{
			BCrypt.NTSTATUS status;
			var buffer = bufferSegment.Array;
			var offset = bufferSegment.Offset;
			var count = bufferSegment.Count;

			if (count > CACHE_THRESHOLD)
			{
				status = (offset == 0) ? BCrypt.BCryptGenRandom(buffer, count) : BCrypt.BCryptGenRandom_PinnedBuffer(buffer, offset, count);
				if (status == BCrypt.NTSTATUS.STATUS_SUCCESS) return;
				throw new CryptographicException((int)status);
			}

			while (true)
			{
				int currentByteCachePosition = Interlocked.Add(ref _byteCachePosition, count);
				if (currentByteCachePosition <= BYTE_CACHE_SIZE && currentByteCachePosition > 0)
				{
					Utils.BlockCopy(_byteCache, currentByteCachePosition - count, buffer, 0, count);
					return;
				}

				lock (_byteCache)
				{
					currentByteCachePosition = _byteCachePosition; // atomic read
					if (currentByteCachePosition > (BYTE_CACHE_SIZE - count) || currentByteCachePosition <= 0)
					{
						status = BCrypt.BCryptGenRandom(_byteCache, BYTE_CACHE_SIZE);
						if (status == BCrypt.NTSTATUS.STATUS_SUCCESS)
						{
							_byteCachePosition = count; // atomic write
							Utils.BlockCopy(_byteCache, 0, buffer, 0, count);
							return;
						}

						// defensive logic to prevent _byteCachePosition from wrapping into valid range due to BCryptGenRandom failures
						if (currentByteCachePosition > BYTE_CACHE_SIZE || currentByteCachePosition < 0) _byteCachePosition = BYTE_CACHE_SIZE;

						throw new CryptographicException((int)status);
					}// if outside the valid range
				}// lock
			}// while(true)
		}//NextBytes()