func makeServerPipeHandle()

in pipe.go [276:345]


func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) {
	path16, err := syscall.UTF16FromString(path)
	if err != nil {
		return 0, &os.PathError{Op: "open", Path: path, Err: err}
	}

	var oa objectAttributes
	oa.Length = unsafe.Sizeof(oa)

	var ntPath unicodeString
	if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil {
		return 0, &os.PathError{Op: "open", Path: path, Err: err}
	}
	defer localFree(ntPath.Buffer)
	oa.ObjectName = &ntPath

	// The security descriptor is only needed for the first pipe.
	if first {
		if sd != nil {
			len := uint32(len(sd))
			sdb := localAlloc(0, len)
			defer localFree(sdb)
			copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
			oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
		} else {
			// Construct the default named pipe security descriptor.
			var dacl uintptr
			if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
				return 0, fmt.Errorf("getting default named pipe ACL: %s", err)
			}
			defer localFree(dacl)

			sdb := &securityDescriptor{
				Revision: 1,
				Control:  cSE_DACL_PRESENT,
				Dacl:     dacl,
			}
			oa.SecurityDescriptor = sdb
		}
	}

	typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS)
	if c.MessageMode {
		typ |= cFILE_PIPE_MESSAGE_TYPE
	}

	disposition := uint32(cFILE_OPEN)
	access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
	if first {
		disposition = cFILE_CREATE
		// By not asking for read or write access, the named pipe file system
		// will put this pipe into an initially disconnected state, blocking
		// client connections until the next call with first == false.
		access = syscall.SYNCHRONIZE
	}

	timeout := int64(-50 * 10000) // 50ms

	var (
		h    syscall.Handle
		iosb ioStatusBlock
	)
	err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err()
	if err != nil {
		return 0, &os.PathError{Op: "open", Path: path, Err: err}
	}

	runtime.KeepAlive(ntPath)
	return h, nil
}