proxy_C_GetSlotList (CK_X_FUNCTION_LIST *self,
                     CK_BBOOL token_present,
                     CK_SLOT_ID_PTR slot_list,
                     CK_ULONG_PTR count)
{
	State *state = (State *)self;
	CK_SLOT_INFO info;
	Mapping *mapping;
	CK_ULONG index;
	CK_RV rv = CKR_OK;
	unsigned int i;

	return_val_if_fail (count != NULL, CKR_ARGUMENTS_BAD);

	p11_lock ();

		if (!PROXY_VALID (state->px)) {
			rv = CKR_CRYPTOKI_NOT_INITIALIZED;
		}

		if (rv == CKR_OK) {
			Mapping *mappings = NULL;
			unsigned int n_mappings = 0;

			if (state->px->mappings) {
				mappings = state->px->mappings;
				n_mappings = state->px->n_mappings;
				state->px->mappings = NULL;
				state->px->n_mappings = 0;
			}
			rv = proxy_list_slots (state->px, mappings, n_mappings);
			if (rv == CKR_OK) {
				free (mappings);
			} else {
				p11_debug ("failed to list slots: %lu", rv);
				state->px->mappings = mappings;
				state->px->n_mappings = n_mappings;
			}
		}

		if (rv == CKR_OK) {
			index = 0;

			/* Go through and build up a map */
			for (i = 0; i < state->px->n_mappings; ++i) {
				mapping = &state->px->mappings[i];

				/* Skip ones without a token if requested */
				if (token_present) {
					rv = (mapping->funcs->C_GetSlotInfo) (mapping->real_slot, &info);
					if (rv != CKR_OK)
						break;
					if (!(info.flags & CKF_TOKEN_PRESENT))
						continue;
				}

				/* Fill in the slot if we can */
				if (slot_list && *count > index)
					slot_list[index] = mapping->wrap_slot;

				++index;
			}

			if (slot_list && *count < index)
				rv = CKR_BUFFER_TOO_SMALL;

			*count = index;
		}

	p11_unlock ();

	return rv;
}
proxy_C_GetSlotList (CK_X_FUNCTION_LIST *self,
                     CK_BBOOL token_present,
                     CK_SLOT_ID_PTR slot_list,
                     CK_ULONG_PTR count)
{
	State *state = (State *)self;
	CK_SLOT_INFO info;
	Mapping *mapping;
	CK_ULONG index;
	CK_RV rv = CKR_OK;
	unsigned int i;

	return_val_if_fail (count != NULL, CKR_ARGUMENTS_BAD);

	p11_lock ();

		if (!PROXY_VALID (state->px)) {
			rv = CKR_CRYPTOKI_NOT_INITIALIZED;
		}

		if (rv == CKR_OK) {
			Mapping *mappings = NULL;
			unsigned int n_mappings = 0;

			if (state->px->mappings) {
				mappings = state->px->mappings;
				n_mappings = state->px->n_mappings;
				state->px->mappings = NULL;
				state->px->n_mappings = 0;
			}
			rv = proxy_list_slots (state->px, mappings, n_mappings);
			if (rv == CKR_OK) {
				free (mappings);
			} else {
				p11_debug ("failed to list slots: %lu", rv);
				state->px->mappings = mappings;
				state->px->n_mappings = n_mappings;
			}
		}

		if (rv == CKR_OK) {
			index = 0;

			 
			for (i = 0; i < state->px->n_mappings; ++i) {
				mapping = &state->px->mappings[i];

				 
				if (token_present) {
					rv = (mapping->funcs->C_GetSlotInfo) (mapping->real_slot, &info);
					if (rv != CKR_OK)
						break;
					if (!(info.flags & CKF_TOKEN_PRESENT))
						continue;
				}

				 
				if (slot_list && *count > index)
					slot_list[index] = mapping->wrap_slot;

				++index;
			}

			if (slot_list && *count < index)
				rv = CKR_BUFFER_TOO_SMALL;

			*count = index;
		}

	p11_unlock ();

	return rv;
}