예제 #1
0
  static UserPrincipal fromSid(long sidAddress) throws IOException {
    String sidString;
    try {
      sidString = ConvertSidToStringSid(sidAddress);
      if (sidString == null) {
        // pre-Windows XP system?
        throw new AssertionError();
      }
    } catch (WindowsException x) {
      throw new IOException("Unable to convert SID to String: " + x.errorString());
    }

    // lookup account; if not available then use the SID as the name
    Account account = null;
    String name;
    try {
      account = LookupAccountSid(sidAddress);
      name = account.domain() + "\\" + account.name();
    } catch (WindowsException x) {
      name = sidString;
    }

    int sidType = (account == null) ? SidTypeUnknown : account.use();
    if ((sidType == SidTypeGroup)
        || (sidType == SidTypeWellKnownGroup)
        || (sidType == SidTypeAlias)) // alias for local group
    {
      return new Group(sidString, sidType, name);
    } else {
      return new User(sidString, sidType, name);
    }
  }
예제 #2
0
  static UserPrincipal lookup(String name) throws IOException {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
      sm.checkPermission(new RuntimePermission("lookupUserInformation"));
    }

    // invoke LookupAccountName to get buffer size needed for SID
    int size = 0;
    try {
      size = LookupAccountName(name, 0L, 0);
    } catch (WindowsException x) {
      if (x.lastError() == ERROR_NONE_MAPPED) throw new UserPrincipalNotFoundException(name);
      throw new IOException(name + ": " + x.errorString());
    }
    assert size > 0;

    // allocate buffer and re-invoke LookupAccountName get SID
    NativeBuffer sidBuffer = NativeBuffers.getNativeBuffer(size);
    try {
      int newSize = LookupAccountName(name, sidBuffer.address(), size);
      if (newSize != size) {
        // can this happen?
        throw new AssertionError("SID change during lookup");
      }

      // return user principal
      return fromSid(sidBuffer.address());
    } catch (WindowsException x) {
      throw new IOException(name + ": " + x.errorString());
    } finally {
      sidBuffer.release();
    }
  }
 @Override
 void wakeup() throws IOException {
   try {
     PostQueuedCompletionStatus(port, WAKEUP_COMPLETION_KEY);
   } catch (WindowsException x) {
     throw new IOException(x.getMessage());
   }
 }
  /** Creates an I/O completion port and a daemon thread to service it */
  WindowsWatchService(WindowsFileSystem fs) throws IOException {
    // create I/O completion port
    long port = 0L;
    try {
      port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0);
    } catch (WindowsException x) {
      throw new IOException(x.getMessage());
    }

    this.poller = new Poller(fs, this, port);
    this.poller.start();
  }
  /**
   * Open/creates file, returning AsynchronousFileChannel to access the file
   *
   * @param pathForWindows The path of the file to open/create
   * @param pathToCheck The path used for permission checks (if security manager)
   * @param pool The thread pool that the channel is associated with
   */
  static AsynchronousFileChannel newAsynchronousFileChannel(
      String pathForWindows,
      String pathToCheck,
      Set<? extends OpenOption> options,
      long pSecurityDescriptor,
      ThreadPool pool)
      throws IOException {
    Flags flags = Flags.toFlags(options);

    // Overlapped I/O required
    flags.overlapped = true;

    // default is reading
    if (!flags.read && !flags.write) {
      flags.read = true;
    }

    // validation
    if (flags.append) throw new UnsupportedOperationException("APPEND not allowed");

    // open file for overlapped I/O
    FileDescriptor fdObj;
    try {
      fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor);
    } catch (WindowsException x) {
      x.rethrowAsIOException(pathForWindows);
      return null;
    }

    // create the AsynchronousFileChannel
    try {
      return WindowsAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool);
    } catch (IOException x) {
      // IOException is thrown if the file handle cannot be associated
      // with the completion port. All we can do is close the file.
      long handle = fdAccess.getHandle(fdObj);
      CloseHandle(handle);
      throw x;
    }
  }
    /** Poller main loop */
    @Override
    public void run() {
      for (; ; ) {
        CompletionStatus info;
        try {
          info = GetQueuedCompletionStatus(port);
        } catch (WindowsException x) {
          // this should not happen
          x.printStackTrace();
          return;
        }

        // wakeup
        if (info.completionKey() == WAKEUP_COMPLETION_KEY) {
          boolean shutdown = processRequests();
          if (shutdown) {
            return;
          }
          continue;
        }

        // map completionKey to get WatchKey
        WindowsWatchKey key = ck2key.get((int) info.completionKey());
        if (key == null) {
          // We get here when a registration is changed. In that case
          // the directory is closed which causes an event with the
          // old completion key.
          continue;
        }

        boolean criticalError = false;
        int errorCode = info.error();
        int messageSize = info.bytesTransferred();
        if (errorCode == ERROR_NOTIFY_ENUM_DIR) {
          // buffer overflow
          key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
        } else if (errorCode != 0 && errorCode != ERROR_MORE_DATA) {
          // ReadDirectoryChangesW failed
          criticalError = true;
        } else {
          // ERROR_MORE_DATA is a warning about incomplete
          // data transfer over TCP/UDP stack. For the case
          // [messageSize] is zero in the most of cases.

          if (messageSize > 0) {
            // process non-empty events.
            processEvents(key, messageSize);
          } else if (errorCode == 0) {
            // insufficient buffer size
            // not described, but can happen.
            key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
          }

          // start read for next batch of changes
          try {
            ReadDirectoryChangesW(
                key.handle(),
                key.buffer().address(),
                CHANGES_BUFFER_SIZE,
                key.watchSubtree(),
                ALL_FILE_NOTIFY_EVENTS,
                key.countAddress(),
                key.overlappedAddress());
          } catch (WindowsException x) {
            // no choice but to cancel key
            criticalError = true;
          }
        }
        if (criticalError) {
          implCancelKey(key);
          key.signal();
        }
      }
    }
    /**
     * Register a directory for changes as follows:
     *
     * <p>1. Open directory 2. Read its attributes (and check it really is a directory) 3. Assign
     * completion key and associated handle with completion port 4. Call ReadDirectoryChangesW to
     * start (async) read of changes 5. Create or return existing key representing registration
     */
    @Override
    Object implRegister(
        Path obj, Set<? extends WatchEvent.Kind<?>> events, WatchEvent.Modifier... modifiers) {
      WindowsPath dir = (WindowsPath) obj;
      boolean watchSubtree = false;

      // FILE_TREE modifier allowed
      for (WatchEvent.Modifier modifier : modifiers) {
        if (modifier == ExtendedWatchEventModifier.FILE_TREE) {
          watchSubtree = true;
        } else {
          if (modifier == null) return new NullPointerException();
          if (modifier instanceof com.sun.nio.file.SensitivityWatchEventModifier)
            continue; // ignore
          return new UnsupportedOperationException("Modifier not supported");
        }
      }

      // open directory
      long handle;
      try {
        handle =
            CreateFile(
                dir.getPathForWin32Calls(),
                FILE_LIST_DIRECTORY,
                (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
                OPEN_EXISTING,
                FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED);
      } catch (WindowsException x) {
        return x.asIOException(dir);
      }

      boolean registered = false;
      try {
        // read attributes and check file is a directory
        WindowsFileAttributes attrs;
        try {
          attrs = WindowsFileAttributes.readAttributes(handle);
        } catch (WindowsException x) {
          return x.asIOException(dir);
        }
        if (!attrs.isDirectory()) {
          return new NotDirectoryException(dir.getPathForExceptionMessage());
        }

        // check if this directory is already registered
        FileKey fk =
            new FileKey(attrs.volSerialNumber(), attrs.fileIndexHigh(), attrs.fileIndexLow());
        WindowsWatchKey existing = fk2key.get(fk);

        // if already registered and we're not changing the subtree
        // modifier then simply update the event and return the key.
        if (existing != null && watchSubtree == existing.watchSubtree()) {
          existing.setEvents(events);
          return existing;
        }

        // Can overflow the int type capacity.
        // Skip WAKEUP_COMPLETION_KEY value.
        int completionKey = ++lastCompletionKey;
        if (completionKey == WAKEUP_COMPLETION_KEY) completionKey = ++lastCompletionKey;

        // associate handle with completion port
        try {
          CreateIoCompletionPort(handle, port, completionKey);
        } catch (WindowsException x) {
          return new IOException(x.getMessage());
        }

        // allocate memory for events, including space for other structures
        // needed to do overlapped I/O
        int size = CHANGES_BUFFER_SIZE + SIZEOF_DWORD + SIZEOF_OVERLAPPED;
        NativeBuffer buffer = NativeBuffers.getNativeBuffer(size);

        long bufferAddress = buffer.address();
        long overlappedAddress = bufferAddress + size - SIZEOF_OVERLAPPED;
        long countAddress = overlappedAddress - SIZEOF_DWORD;

        // zero the overlapped structure
        UNSAFE.setMemory(overlappedAddress, SIZEOF_OVERLAPPED, (byte) 0);

        // start async read of changes to directory
        try {
          createAndAttachEvent(overlappedAddress);

          ReadDirectoryChangesW(
              handle,
              bufferAddress,
              CHANGES_BUFFER_SIZE,
              watchSubtree,
              ALL_FILE_NOTIFY_EVENTS,
              countAddress,
              overlappedAddress);
        } catch (WindowsException x) {
          closeAttachedEvent(overlappedAddress);
          buffer.release();
          return new IOException(x.getMessage());
        }

        WindowsWatchKey watchKey;
        if (existing == null) {
          // not registered so create new watch key
          watchKey =
              new WindowsWatchKey(dir, watcher, fk)
                  .init(
                      handle,
                      events,
                      watchSubtree,
                      buffer,
                      countAddress,
                      overlappedAddress,
                      completionKey);
          // map file key to watch key
          fk2key.put(fk, watchKey);
        } else {
          // directory already registered so need to:
          // 1. remove mapping from old completion key to existing watch key
          // 2. release existing key's resources (handle/buffer)
          // 3. re-initialize key with new handle/buffer
          ck2key.remove(existing.completionKey());
          releaseResources(existing);
          watchKey =
              existing.init(
                  handle,
                  events,
                  watchSubtree,
                  buffer,
                  countAddress,
                  overlappedAddress,
                  completionKey);
        }
        // map completion map to watch key
        ck2key.put(completionKey, watchKey);

        registered = true;
        return watchKey;

      } finally {
        if (!registered) CloseHandle(handle);
      }
    }