implemented FindFirstStreamW() and FindNextStreamW() (untested!)
Modified: trunk/reactos/include/ndk/iotypes.h
Modified: trunk/reactos/lib/kernel32/file/find.c
Modified: trunk/reactos/lib/kernel32/kernel32.def
Modified: trunk/reactos/w32api/include/winbase.h

Modified: trunk/reactos/include/ndk/iotypes.h
--- trunk/reactos/include/ndk/iotypes.h	2006-01-15 01:24:59 UTC (rev 20881)
+++ trunk/reactos/include/ndk/iotypes.h	2006-01-15 03:11:31 UTC (rev 20882)
@@ -320,6 +320,15 @@
     BOOLEAN Directory;
 } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
 
+typedef struct _FILE_STREAM_INFORMATION
+{
+    ULONG NextEntryOffset;
+    ULONG StreamNameLength;
+    LARGE_INTEGER StreamSize;
+    LARGE_INTEGER StreamAllocationSize;
+    WCHAR StreamName[1];
+} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION;
+
 typedef struct _FILE_NETWORK_OPEN_INFORMATION
 {
     LARGE_INTEGER CreationTime;

Modified: trunk/reactos/lib/kernel32/file/find.c
--- trunk/reactos/lib/kernel32/file/find.c	2006-01-15 01:24:59 UTC (rev 20881)
+++ trunk/reactos/lib/kernel32/file/find.c	2006-01-15 03:11:31 UTC (rev 20882)
@@ -19,10 +19,6 @@
 
 /* TYPES ********************************************************************/
 
-#ifndef offsetof
-#define	offsetof(TYPE, MEMBER)	((size_t) &( ((TYPE *) 0)->MEMBER ))
-#endif
-
 #define FIND_DATA_SIZE	(16*1024)
 
 typedef struct _KERNEL32_FIND_FILE_DATA
@@ -32,9 +28,41 @@
    PFILE_BOTH_DIR_INFORMATION pFileInfo;
 } KERNEL32_FIND_FILE_DATA, *PKERNEL32_FIND_FILE_DATA;
 
+typedef struct _KERNEL32_FIND_STREAM_DATA
+{
+    STREAM_INFO_LEVELS InfoLevel;
+    PFILE_STREAM_INFORMATION pFileStreamInfo;
+    PFILE_STREAM_INFORMATION pCurrent;
+} KERNEL32_FIND_STREAM_DATA, *PKERNEL32_FIND_STREAM_DATA;
 
+typedef enum _KERNEL32_FIND_DATA_TYPE
+{
+    FileFind,
+    StreamFind
+} KERNEL32_FIND_DATA_TYPE;
+
+typedef struct _KERNEL32_FIND_DATA_HEADER
+{
+    KERNEL32_FIND_DATA_TYPE Type;
+} KERNEL32_FIND_DATA_HEADER, *PKERNEL32_FIND_DATA_HEADER;
+
+
 /* FUNCTIONS ****************************************************************/
 
+static __inline PKERNEL32_FIND_FILE_DATA
+HandleToFindData(IN HANDLE Handle)
+{
+    PKERNEL32_FIND_DATA_HEADER FindData = (PKERNEL32_FIND_DATA_HEADER)Handle;
+
+    if (Handle != NULL && Handle != INVALID_HANDLE_VALUE &&
+        FindData->Type == FileFind)
+    {
+        return (PKERNEL32_FIND_FILE_DATA)(FindData + 1);
+    }
+
+    return NULL;
+}
+
 VOID
 InternalCopyFindDataW(LPWIN32_FIND_DATAW            lpFindFileData,
                       PFILE_BOTH_DIR_INFORMATION    lpFileInfo)
@@ -122,14 +150,23 @@
         PUNICODE_STRING SearchPattern
 	)
 {
+	PKERNEL32_FIND_DATA_HEADER IHeader;
 	PKERNEL32_FIND_FILE_DATA IData;
 	IO_STATUS_BLOCK IoStatusBlock;
 	NTSTATUS Status;
 
 	DPRINT("InternalFindNextFile(%lx)\n", hFindFile);
 
-	IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
+        IHeader = (PKERNEL32_FIND_DATA_HEADER)hFindFile;
+        if (hFindFile == NULL || hFindFile == INVALID_HANDLE_VALUE ||
+            IHeader->Type != FileFind)
+        {
+            SetLastError (ERROR_INVALID_HANDLE);
+            return FALSE;
+        }
 
+        IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
+
         while (1)
         {
             if (IData->pFileInfo->NextEntryOffset != 0)
@@ -178,6 +215,7 @@
 	)
 {
 	OBJECT_ATTRIBUTES ObjectAttributes;
+	PKERNEL32_FIND_DATA_HEADER IHeader;
 	PKERNEL32_FIND_FILE_DATA IData;
 	IO_STATUS_BLOCK IoStatusBlock;
 	UNICODE_STRING NtPathU;
@@ -302,10 +340,11 @@
 
 	DPRINT("NtPathU \'%S\'\n", NtPathU.Buffer);
 
-	IData = RtlAllocateHeap (hProcessHeap,
-	                         HEAP_ZERO_MEMORY,
-	                         sizeof(KERNEL32_FIND_FILE_DATA) + FIND_DATA_SIZE);
-	if (NULL == IData)
+	IHeader = RtlAllocateHeap (hProcessHeap,
+	                           HEAP_ZERO_MEMORY,
+                                   sizeof(KERNEL32_FIND_DATA_HEADER) +
+	                               sizeof(KERNEL32_FIND_FILE_DATA) + FIND_DATA_SIZE);
+	if (NULL == IHeader)
 	{
 	   RtlFreeHeap (hProcessHeap,
 	                0,
@@ -320,6 +359,9 @@
 	   return NULL;
 	}
 
+ 	IHeader->Type = FileFind;
+ 	IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
+
 	/* change pattern: "*.*" --> "*" */
 	if (wcscmp (SearchPattern, L"*.*"))
 	{
@@ -348,7 +390,7 @@
 
 	if (!NT_SUCCESS(Status))
 	{
-	   RtlFreeHeap (hProcessHeap, 0, IData);
+	   RtlFreeHeap (hProcessHeap, 0, IHeader);
 	   if (NULL != SlashlessFileName)
 	   {
 	      RtlFreeHeap(hProcessHeap,
@@ -362,7 +404,7 @@
 	IData->pFileInfo->FileIndex = 0;
         IData->DirectoryOnly = DirectoryOnly;
 
-        bResult = InternalFindNextFile((HANDLE)IData, &PatternStr);
+        bResult = InternalFindNextFile((HANDLE)IHeader, &PatternStr);
 	if (NULL != SlashlessFileName)
 	{
 	   RtlFreeHeap(hProcessHeap,
@@ -372,11 +414,11 @@
 
         if (!bResult)
         {
-            FindClose((HANDLE)IData);
+            FindClose((HANDLE)IHeader);
             return NULL;
         }
 
-	return IData;
+	return (HANDLE)IHeader;
 }
 
 
@@ -390,6 +432,7 @@
 	LPWIN32_FIND_DATAA	lpFindFileData
 	)
 {
+	PKERNEL32_FIND_DATA_HEADER IHeader;
 	PKERNEL32_FIND_FILE_DATA IData;
 	UNICODE_STRING FileNameU;
 	ANSI_STRING FileName;
@@ -407,16 +450,18 @@
 		                             &FileName,
 		                             TRUE);
 
-	IData = InternalFindFirstFile (FileNameU.Buffer, FALSE);
+	IHeader = InternalFindFirstFile (FileNameU.Buffer, FALSE);
 
 	RtlFreeUnicodeString (&FileNameU);
 
-	if (IData == NULL)
+	if (IHeader == NULL)
 	{
 		DPRINT("Failing request\n");
 		return INVALID_HANDLE_VALUE;
 	}
 
+	IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
+
 	DPRINT("IData->pFileInfo->FileNameLength %d\n",
 	       IData->pFileInfo->FileNameLength);
 
@@ -424,7 +469,7 @@
         InternalCopyFindDataA(lpFindFileData, IData->pFileInfo);
 
 
-	return (HANDLE)IData;
+	return (HANDLE)IHeader;
 }
 
 
@@ -439,20 +484,14 @@
 {
 	PKERNEL32_FIND_FILE_DATA IData;
 
-	if (hFindFile == INVALID_HANDLE_VALUE)
-	{
-		SetLastError (ERROR_INVALID_HANDLE);
-		DPRINT("Failing request\n");
-		return FALSE;
-	}
-
-	IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
 	if (!InternalFindNextFile (hFindFile, NULL))
 	{
 		DPRINT("InternalFindNextFile() failed\n");
 		return FALSE;
 	}
 
+	IData = (PKERNEL32_FIND_FILE_DATA)((PKERNEL32_FIND_DATA_HEADER)hFindFile + 1);
+
 	DPRINT("IData->pFileInfo->FileNameLength %d\n",
 	       IData->pFileInfo->FileNameLength);
 
@@ -472,7 +511,7 @@
 	HANDLE	hFindFile
 	)
 {
-	PKERNEL32_FIND_FILE_DATA IData;
+	PKERNEL32_FIND_DATA_HEADER IHeader;
 
 	DPRINT("FindClose(hFindFile %x)\n",hFindFile);
 
@@ -482,11 +521,34 @@
 		return FALSE;
 	}
 
-	IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
+	IHeader = (PKERNEL32_FIND_DATA_HEADER)hFindFile;
 
-	CloseHandle (IData->DirectoryHandle);
-	RtlFreeHeap (hProcessHeap, 0, IData);
+	switch (IHeader->Type)
+	{
+		case FileFind:
+		{
+			PKERNEL32_FIND_FILE_DATA IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
+			CloseHandle (IData->DirectoryHandle);
+			break;
+		}
 
+		case StreamFind:
+		{
+			PKERNEL32_FIND_STREAM_DATA IData = (PKERNEL32_FIND_STREAM_DATA)(IHeader + 1);
+			if (IData->pFileStreamInfo != NULL)
+			{
+				RtlFreeHeap (hProcessHeap, 0, IData->pFileStreamInfo);
+			}
+			break;
+		}
+
+		default:
+			SetLastError (ERROR_INVALID_HANDLE);
+			return FALSE;
+	}
+
+	RtlFreeHeap (hProcessHeap, 0, IHeader);
+
 	return TRUE;
 }
 
@@ -522,20 +584,14 @@
 {
 	PKERNEL32_FIND_FILE_DATA IData;
 
-	if (hFindFile == INVALID_HANDLE_VALUE)
-	{
-		SetLastError (ERROR_INVALID_HANDLE);
-		DPRINT("Failing request\n");
-		return FALSE;
-	}
-
-	IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
 	if (!InternalFindNextFile(hFindFile, NULL))
 	{
 		DPRINT("Failing request\n");
 		return FALSE;
 	}
 
+	IData = (PKERNEL32_FIND_FILE_DATA)((PKERNEL32_FIND_DATA_HEADER)hFindFile + 1);
+
 	/* copy data into WIN32_FIND_DATA structure */
         InternalCopyFindDataW(lpFindFileData, IData->pFileInfo);
 
@@ -555,6 +611,7 @@
                   LPVOID                lpSearchFilter,
                   DWORD                 dwAdditionalFlags)
 {
+    PKERNEL32_FIND_DATA_HEADER IHeader;
     PKERNEL32_FIND_FILE_DATA IData;
 
     if (fInfoLevelId != FindExInfoStandard)
@@ -570,17 +627,19 @@
             return INVALID_HANDLE_VALUE;
         }
 
-        IData = InternalFindFirstFile (lpFileName, fSearchOp == FindExSearchLimitToDirectories ? TRUE : FALSE);
-	if (IData == NULL)
+        IHeader = InternalFindFirstFile (lpFileName, fSearchOp == FindExSearchLimitToDirectories ? TRUE : FALSE);
+	if (IHeader == NULL)
 	{
 		DPRINT("Failing request\n");
 		return INVALID_HANDLE_VALUE;
 	}
 
-	/* copy data into WIN32_FIND_DATA structure */
+        IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
+
+        /* copy data into WIN32_FIND_DATA structure */
         InternalCopyFindDataW((LPWIN32_FIND_DATAW)lpFindFileData, IData->pFileInfo);
 
-	return (HANDLE)IData;
+	return (HANDLE)IHeader;
     }
     SetLastError(ERROR_INVALID_PARAMETER);
     return INVALID_HANDLE_VALUE;
@@ -600,6 +659,7 @@
 	DWORD			dwAdditionalFlags
 	)
 {
+    PKERNEL32_FIND_DATA_HEADER IHeader;
     PKERNEL32_FIND_FILE_DATA IData;
     UNICODE_STRING FileNameU;
     ANSI_STRING FileNameA;
@@ -625,22 +685,263 @@
 	else
             RtlOemStringToUnicodeString (&FileNameU, &FileNameA, TRUE);
 
-	IData = InternalFindFirstFile (FileNameU.Buffer, FALSE);
+	IHeader = InternalFindFirstFile (FileNameU.Buffer, FALSE);
 
 	RtlFreeUnicodeString (&FileNameU);
 
-	if (IData == NULL)
+	if (IHeader == NULL)
 	{
 		DPRINT("Failing request\n");
 		return INVALID_HANDLE_VALUE;
 	}
 
+        IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
+
 	/* copy data into WIN32_FIND_DATA structure */
         InternalCopyFindDataA(lpFindFileData, IData->pFileInfo);
+
+        return (HANDLE)IHeader;
     }
     SetLastError(ERROR_INVALID_PARAMETER);
     return INVALID_HANDLE_VALUE;
 }
 
 
+static VOID
+InternalCopyStreamInfo(IN OUT PKERNEL32_FIND_STREAM_DATA IData,
+                       OUT LPVOID lpFindStreamData)
+{
+    ASSERT(IData->pCurrent != NULL);
+
+    switch (IData->InfoLevel)
+    {
+        case FindStreamInfoStandard:
+        {
+            ULONG StreamNameLen;
+            WIN32_FIND_STREAM_DATAW *StreamData = (WIN32_FIND_STREAM_DATAW*)lpFindStreamData;
+
+            StreamNameLen = IData->pCurrent->StreamNameLength;
+            if (StreamNameLen > sizeof(StreamData->cStreamName) - sizeof(WCHAR))
+                StreamNameLen = sizeof(StreamData->cStreamName) - sizeof(WCHAR);
+
+            StreamData->StreamSize.QuadPart = IData->pCurrent->StreamSize.QuadPart;
+            RtlCopyMemory(StreamData->cStreamName,
+                          IData->pCurrent->StreamName,
+                          StreamNameLen);
+            StreamData->cStreamName[StreamNameLen / sizeof(WCHAR)] = L'\0';
+            break;
+        }
+
+        default:
+            ASSERT(FALSE);
+            break;
+    }
+}
+
+
+/*
+ * @implemented
+ */
+HANDLE
+WINAPI
+FindFirstStreamW(IN LPCWSTR lpFileName,
+                 IN STREAM_INFO_LEVELS InfoLevel,
+                 OUT LPVOID lpFindStreamData,
+                 IN DWORD dwFlags)
+{
+    PKERNEL32_FIND_DATA_HEADER IHeader = NULL;
+    PKERNEL32_FIND_STREAM_DATA IData = NULL;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+    UNICODE_STRING NtPathU;
+    HANDLE FileHandle = NULL;
+    NTSTATUS Status;
+    ULONG BufferSize = 0;
+
+    if (dwFlags != 0 || InfoLevel != FindStreamInfoStandard ||
+        lpFindStreamData == NULL)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return INVALID_HANDLE_VALUE;
+    }
+
+    /* validate & translate the filename */
+    if (!RtlDosPathNameToNtPathName_U(lpFileName,
+                                      &NtPathU,
+                                      NULL,
+                                      NULL))
+    {
+        SetLastError(ERROR_PATH_NOT_FOUND);
+        return INVALID_HANDLE_VALUE;
+    }
+
+    /* open the file */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &NtPathU,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtCreateFile(&FileHandle,
+                          0,
+                          &ObjectAttributes,
+                          &IoStatusBlock,
+                          NULL,
+                          0,
+                          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+                          FILE_OPEN,
+                          0,
+                          NULL,
+                          0);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Cleanup;
+    }
+
+    /* create the search context */
+    IHeader = RtlAllocateHeap(hProcessHeap,
+                              0,
+                              sizeof(KERNEL32_FIND_DATA_HEADER) +
+                                  sizeof(KERNEL32_FIND_STREAM_DATA));
+    if (IHeader == NULL)
+    {
+        Status = STATUS_NO_MEMORY;
+        goto Cleanup;
+    }
+
+    IHeader->Type = StreamFind;
+    IData = (PKERNEL32_FIND_STREAM_DATA)(IHeader + 1);
+
+    /* capture all information about the streams */
+    IData->InfoLevel = InfoLevel;
+    IData->pCurrent = NULL;
+    IData->pFileStreamInfo = NULL;
+
+    do
+    {
+        BufferSize += 0x1000;
+
+        if (IData->pFileStreamInfo == NULL)
+        {
+            IData->pFileStreamInfo = RtlAllocateHeap(hProcessHeap,
+                                                     0,
+                                                     BufferSize);
+            if (IData->pFileStreamInfo == NULL)
+            {
+                Status = STATUS_NO_MEMORY;
+                break;
+            }
+        }
+        else
+        {
+            PFILE_STREAM_INFORMATION pfsi;
+
+            pfsi = RtlReAllocateHeap(hProcessHeap,
+                                     0,
+                                     IData->pFileStreamInfo,
+                                     BufferSize);
+            if (pfsi == NULL)
+            {
+                Status = STATUS_NO_MEMORY;
+                break;
+            }
+
+            IData->pFileStreamInfo = pfsi;
+        }
+
+        Status = NtQueryInformationFile(FileHandle,
+                                        &IoStatusBlock,
+                                        IData->pFileStreamInfo,
+                                        BufferSize,
+                                        FileStreamInformation);
+
+    } while (Status == STATUS_BUFFER_TOO_SMALL);
+
+    if (NT_SUCCESS(Status))
+    {
+        NtClose(FileHandle);
+        FileHandle = NULL;
+
+        /* select the first stream and return the information */
+        IData->pCurrent = IData->pFileStreamInfo;
+        InternalCopyStreamInfo(IData,
+                               lpFindStreamData);
+
+        /* all done */
+        Status = STATUS_SUCCESS;
+    }
+
+Cleanup:
+    if (FileHandle != NULL)
+    {
+        NtClose(FileHandle);
+    }
+
+    RtlFreeUnicodeString(&NtPathU);
+
+    if (!NT_SUCCESS(Status))
+    {
+        if (IHeader != NULL)
+        {
+            if (IData->pFileStreamInfo != NULL)
+            {
+                RtlFreeHeap(hProcessHeap,
+                            0,
+                            IData->pFileStreamInfo);
+            }
+
+            RtlFreeHeap(hProcessHeap,
+                        0,
+                        IHeader);
+        }
+
+        SetLastErrorByStatus(Status);
+        return INVALID_HANDLE_VALUE;
+    }
+
+    return (HANDLE)IHeader;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+FindNextStreamW(IN HANDLE hFindStream,
+                OUT LPVOID lpFindStreamData)
+{
+    PKERNEL32_FIND_DATA_HEADER IHeader;
+    PKERNEL32_FIND_STREAM_DATA IData;
+
+    IHeader = (PKERNEL32_FIND_DATA_HEADER)hFindStream;
+    if (hFindStream == NULL || hFindStream == INVALID_HANDLE_VALUE ||
+        IHeader->Type != StreamFind)
+    {
+        SetLastError (ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    IData = (PKERNEL32_FIND_STREAM_DATA)(IHeader + 1);
+
+    /* select next stream if possible */
+    if (IData->pCurrent->NextEntryOffset != 0)
+    {
+        IData->pCurrent = (PFILE_STREAM_INFORMATION)((ULONG_PTR)IData->pFileStreamInfo +
+                                                     IData->pCurrent->NextEntryOffset);
+    }
+    else
+    {
+        SetLastError(ERROR_HANDLE_EOF);
+        return FALSE;
+    }
+
+    /* return the information */
+    InternalCopyStreamInfo(IData,
+                           lpFindStreamData);
+
+    return TRUE;
+}
+
+
 /* EOF */

Modified: trunk/reactos/lib/kernel32/kernel32.def
--- trunk/reactos/lib/kernel32/kernel32.def	2006-01-15 01:24:59 UTC (rev 20881)
+++ trunk/reactos/lib/kernel32/kernel32.def	2006-01-15 03:11:31 UTC (rev 20882)
@@ -243,9 +243,11 @@
 FindFirstFileExA@24
 FindFirstFileExW@24
 FindFirstFileW@8
+FindFirstStreamW@16
 FindNextChangeNotification@4
 FindNextFileA@8
 FindNextFileW@8
+FindNextStreamW@8
 FindFirstVolumeA@8
 FindFirstVolumeMountPointA@12
 FindFirstVolumeMountPointW@12

Modified: trunk/reactos/w32api/include/winbase.h
--- trunk/reactos/w32api/include/winbase.h	2006-01-15 01:24:59 UTC (rev 20881)
+++ trunk/reactos/w32api/include/winbase.h	2006-01-15 03:11:31 UTC (rev 20882)
@@ -809,6 +809,15 @@
 	WCHAR cFileName[MAX_PATH];
 	WCHAR cAlternateFileName[14];
 } WIN32_FIND_DATAW,*PWIN32_FIND_DATAW,*LPWIN32_FIND_DATAW;
+#if (_WIN32_WINNT >= 0x0501)
+typedef enum _STREAM_INFO_LEVELS {
+	FindStreamInfoStandard
+} STREAM_INFO_LEVELS;
+typedef struct _WIN32_FIND_STREAM_DATAW {
+	LARGE_INTEGER StreamSize;
+	WCHAR cStreamName[MAX_PATH + 36];
+} WIN32_FIND_STREAM_DATAW, *PWIN32_FIND_STREAM_DATAW, *LPWIN32_FIND_STREAM_DATAW;
+#endif
 typedef struct _WIN32_STREAM_ID {
 	DWORD dwStreamId;
 	DWORD dwStreamAttributes;
@@ -1288,6 +1297,9 @@
 HANDLE WINAPI FindFirstFileW(LPCWSTR,LPWIN32_FIND_DATAW);
 HANDLE WINAPI FindFirstFileExA(LPCSTR,FINDEX_INFO_LEVELS,PVOID,FINDEX_SEARCH_OPS,PVOID,DWORD);
 HANDLE WINAPI FindFirstFileExW(LPCWSTR,FINDEX_INFO_LEVELS,PVOID,FINDEX_SEARCH_OPS,PVOID,DWORD);
+#if (_WIN32_WINNT >= 0x0501)
+HANDLE WINAPI FindFirstStreamW(LPCWSTR,STREAM_INFO_LEVELS,LPVOID,DWORD);
+#endif
 BOOL WINAPI FindFirstFreeAce(PACL,PVOID*);
 #if (_WIN32_WINNT >= 0x0500)
 HANDLE WINAPI FindFirstVolumeA(LPCSTR,DWORD);
@@ -1298,6 +1310,9 @@
 BOOL WINAPI FindNextChangeNotification(HANDLE);
 BOOL WINAPI FindNextFileA(HANDLE,LPWIN32_FIND_DATAA);
 BOOL WINAPI FindNextFileW(HANDLE,LPWIN32_FIND_DATAW);
+#if (_WIN32_WINNT >= 0x0501)
+BOOL WINAPI FindNextStreamW(HANDLE,LPVOID);
+#endif
 #if (_WIN32_WINNT >= 0x0500)
 BOOL WINAPI FindNextVolumeA(HANDLE,LPCSTR,DWORD);
 BOOL WINAPI FindNextVolumeW(HANDLE,LPWSTR,DWORD);
@@ -1988,6 +2003,9 @@
 #ifdef UNICODE
 typedef STARTUPINFOW STARTUPINFO,*LPSTARTUPINFO;
 typedef WIN32_FIND_DATAW WIN32_FIND_DATA,*LPWIN32_FIND_DATA;
+#if (_WIN32_WINNT >= 0x0501)
+typedef WIN32_FIND_STREAM_DATAW WIN32_FIND_STREAM_DATA,*LPWIN32_FIND_STREAM_DATA;
+#endif
 typedef HW_PROFILE_INFOW HW_PROFILE_INFO,*LPHW_PROFILE_INFO;
 typedef ENUMRESLANGPROCW ENUMRESLANGPROC;
 typedef ENUMRESNAMEPROCW ENUMRESNAMEPROC;