
What do you think about the following functions?
rcpp::win::file_handle clone(rcpp::win::file_handle const & f) { HANDLE h; BOOL r = ::DuplicateHandle(GetCurrentProcess(), f.get(), GetCurrentProcess(), &h, 0, FALSE, DUPLICATE_SAME_ACCESS);
if (r == FALSE) return rcpp::win::file_handle(); // or throw an exception
return rcpp::win::file_handle(h); }
rcpp::win::kernel_handle clone(rcpp::win::kernel_handle const & f) { HANDLE h; BOOL r = ::DuplicateHandle(GetCurrentProcess(), f.get(), GetCurrentProcess(), &h, 0, FALSE, DUPLICATE_SAME_ACCESS);
if (r == FALSE) return rcpp::win::kernel_handle(); // or throw an exception
return rcpp::win::kernel_handle(h); }
In `clone(rcpp::win::file_handle const &)`, what if `h` is `INVALID_HANDLE_VALUE` and `r` is not `FALSE` (`DuplicateHandle` succeeded, but the resulting `HANDLE` was `INVALID_HANDLE_VALUE`)? Then the function would return an "empty" `rcpp::win::file_handle` and the `INVALID_HANDLE_VALUE` `HANDLE` would never be closed. Similarly, if `DuplicateHandle` could set `h` to `NULL` in `clone(rcpp::win::kernel_handle const &)`, then the `NULL` `HANDLE` would never be closed. I know, you're thinking that this is picky. Yes, it's really picky, but I can't help from thinking about this case, especially because the MSDN documentation does not definitively state that this can not happen. I also looked at the documentation for `CloseHandle` to see if it can not accept `NULL` or `INVALID_HANDLE_VALUE`, but there is nothing on that issue, either. (If `CloseHandle` did not accept `NULL`, for example, then `DuplicateHandle` could never use `NULL` for the resulting `HANDLE` value.) I like the solution that you had, which is to use `boost::optional<HANDLE>` with invalid value `boost::none`.