Eric Kohl <eric.kohl_at_t-online.de>
Implement CaptureAndConvertAnsiArg, CaptureStringArg,
OpenAndMapForRead, RetreiveFileSecurity, StampFileSecurity,
TakeOwnershipOfFile, and UnmapAndCloseFile.

diff --git a/dlls/setupapi/misc.c b/dlls/setupapi/misc.c
index ad6b123..d20f9ee 100644
--- a/dlls/setupapi/misc.c
+++ b/dlls/setupapi/misc.c
@@ -463,6 +463,19 @@
 }
 
 
+/**************************************************************************
+ * DelayedMove [SETUPAPI.@]
+ *
+ * Moves a file upon the next reboot.
+ *
+ * PARAMS
+ *     lpExistingFileName  [I] Current file name
+ *     lpNewFileName       [I] New file name
+ *
+ * RETURNS
+ *     Success: TRUE
+ *     Failure: FALSE
+ */
 BOOL WINAPI DelayedMove(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
 {
     return MoveFileExW(lpExistingFileName, lpNewFileName,
@@ -470,6 +483,19 @@
 }
 
 
+/**************************************************************************
+ * FileExists [SETUPAPI.@]
+ *
+ * Checks whether a file exists.
+ *
+ * PARAMS
+ *     lpFileName     [I] Name of the file to check
+ *     lpNewFileName  [O] Optional information about the existing file
+ *
+ * RETURNS
+ *     Success: TRUE
+ *     Failure: FALSE
+ */
 BOOL WINAPI FileExists(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFileFindData)
 {
     WIN32_FIND_DATAW FindData;
@@ -493,5 +519,316 @@
     if (lpFileFindData)
         memcpy(lpFileFindData, &FindData, sizeof(WIN32_FIND_DATAW));
 
+    SetErrorMode(uErrorMode);
+
     return TRUE;
 }
+
+
+/**************************************************************************
+ * CaptureStringArg [SETUPAPI.@]
+ *
+ * Captures a UNICODE string.
+ *
+ * PARAMS
+ *     lpSrc  [I] UNICODE string to be captured
+ *     lpDst  [O] Pointer to the captured UNICODE string
+ *
+ * RETURNS
+ *     Success: ERROR_SUCCESS
+ *     Failure: ERROR_INVALID_PARAMETER
+ *
+ * NOTE
+ *     Call MyFree to release the captured UNICODE string.
+ */
+DWORD WINAPI CaptureStringArg(LPCWSTR pSrc, LPWSTR *pDst)
+{
+    if (pDst == NULL)
+        return ERROR_INVALID_PARAMETER;
+
+    *pDst = DuplicateString(pSrc);
+
+    return ERROR_SUCCESS;
+}
+
+
+/**************************************************************************
+ * CaptureAndConvertAnsiArg [SETUPAPI.@]
+ *
+ * Captures an ANSI string and converts it to a UNICODE string.
+ *
+ * PARAMS
+ *     lpSrc  [I] ANSI string to be captured
+ *     lpDst  [O] Pointer to the captured UNICODE string
+ *
+ * RETURNS
+ *     Success: ERROR_SUCCESS
+ *     Failure: ERROR_INVALID_PARAMETER
+ *
+ * NOTE
+ *     Call MyFree to release the captured UNICODE string.
+ */
+DWORD WINAPI CaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst)
+{
+    if (pDst == NULL)
+        return ERROR_INVALID_PARAMETER;
+
+    *pDst = MultiByteToUnicode(pSrc, CP_ACP);
+
+    return ERROR_SUCCESS;
+}
+
+
+/**************************************************************************
+ * OpenAndMapFileForRead [SETUPAPI.@]
+ *
+ * Open and map a file to a buffer.
+ *
+ * PARAMS
+ *     lpFileName [I] Name of the file to be opened
+ *     lpSize     [O] Pointer to the file size
+ *     lpFile     [0] Pointer to the file handle
+ *     lpMapping  [0] Pointer to the mapping handle
+ *     lpBuffer   [0] Pointer to the file buffer
+ *
+ * RETURNS
+ *     Success: ERROR_SUCCESS
+ *     Failure: Other
+ *
+ * NOTE
+ *     Call UnmapAndCloseFile to release the file.
+ */
+DWORD WINAPI OpenAndMapFileForRead(LPCWSTR lpFileName,
+                                   LPDWORD lpSize,
+                                   LPHANDLE lpFile,
+                                   LPHANDLE lpMapping,
+                                   LPVOID *lpBuffer)
+{
+    DWORD dwError;
+
+    TRACE("%s %p %p %p %p\n",
+          debugstr_w(lpFileName), lpSize, lpFile, lpMapping, lpBuffer);
+
+    *lpFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
+                          OPEN_EXISTING, 0, NULL);
+    if (*lpFile == INVALID_HANDLE_VALUE)
+        return GetLastError();
+
+    *lpSize = GetFileSize(*lpFile, NULL);
+    if (*lpSize == INVALID_FILE_SIZE)
+    {
+        dwError = GetLastError();
+        CloseHandle(*lpFile);
+        return dwError;
+    }
+
+    *lpMapping = CreateFileMappingW(*lpFile, NULL, PAGE_READONLY, 0,
+                                    *lpSize, NULL);
+    if (*lpMapping == NULL)
+    {
+        dwError = GetLastError();
+        CloseHandle(*lpFile);
+        return dwError;
+    }
+
+    *lpBuffer = MapViewOfFile(*lpMapping, FILE_MAP_READ, 0, 0, *lpSize);
+    if (*lpBuffer == NULL)
+    {
+        dwError = GetLastError();
+        CloseHandle(*lpMapping);
+        CloseHandle(*lpFile);
+        return dwError;
+    }
+
+    return ERROR_SUCCESS;
+}
+
+
+/**************************************************************************
+ * UnmapAndCloseFile [SETUPAPI.@]
+ *
+ * Unmap and close a mapped file.
+ *
+ * PARAMS
+ *     hFile    [I] Handle to the file
+ *     hMapping [I] Handle to the file mapping
+ *     lpBuffer [I] Pointer to the file buffer
+ *
+ * RETURNS
+ *     Success: TRUE
+ *     Failure: FALSE
+ */
+BOOL WINAPI UnmapAndCloseFile(HANDLE hFile, HANDLE hMapping, LPVOID lpBuffer)
+{
+    TRACE("%p %p %p\n",
+          hFile, hMapping, lpBuffer);
+
+    if (!UnmapViewOfFile(lpBuffer))
+        return FALSE;
+
+    if (!CloseHandle(hMapping))
+        return FALSE;
+
+    if (!CloseHandle(hFile))
+        return FALSE;
+
+    return TRUE;
+}
+
+
+/**************************************************************************
+ * StampFileSecurity [SETUPAPI.@]
+ *
+ * Assign a new security descriptor to the given file.
+ *
+ * PARAMS
+ *     lpFileName          [I] Name of the file
+ *     pSecurityDescriptor [I] New security descriptor
+ *
+ * RETURNS
+ *     Success: ERROR_SUCCESS
+ *     Failure: other
+ */
+DWORD WINAPI StampFileSecurity(LPCWSTR lpFileName, PSECURITY_DESCRIPTOR pSecurityDescriptor)
+{
+    TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor);
+
+    if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
+                          GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+                          pSecurityDescriptor))
+        return GetLastError();
+
+    return ERROR_SUCCESS;
+}
+
+
+/**************************************************************************
+ * TakeOwnershipOfFile [SETUPAPI.@]
+ *
+ * Takes the ownership of the given file.
+ *
+ * PARAMS
+ *     lpFileName [I] Name of the file
+ *
+ * RETURNS
+ *     Success: ERROR_SUCCESS
+ *     Failure: other
+ */
+DWORD WINAPI TakeOwnershipOfFile(LPCWSTR lpFileName)
+{
+    SECURITY_DESCRIPTOR SecDesc;
+    HANDLE hToken = NULL;
+    PTOKEN_OWNER pOwner = NULL;
+    DWORD dwError;
+    DWORD dwSize;
+
+    TRACE("%s\n", debugstr_w(lpFileName));
+
+    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
+        return GetLastError();
+
+    if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &dwSize))
+    {
+        goto fail;
+    }
+
+    pOwner = (PTOKEN_OWNER)MyMalloc(dwSize);
+    if (pOwner == NULL)
+    {
+        CloseHandle(hToken);
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+    if (!GetTokenInformation(hToken, TokenOwner, pOwner, dwSize, &dwSize))
+    {
+        goto fail;
+    }
+
+    if (!InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION))
+    {
+        goto fail;
+    }
+
+    if (!SetSecurityDescriptorOwner(&SecDesc, pOwner->Owner, FALSE))
+    {
+        goto fail;
+    }
+
+    if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, &SecDesc))
+    {
+        goto fail;
+    }
+
+    MyFree(pOwner);
+    CloseHandle(hToken);
+
+    return ERROR_SUCCESS;
+
+fail:;
+    dwError = GetLastError();
+
+    if (pOwner != NULL)
+        MyFree(pOwner);
+
+    if (hToken != NULL)
+        CloseHandle(hToken);
+
+    return dwError;
+}
+
+
+/**************************************************************************
+ * RetreiveFileSecurity [SETUPAPI.@]
+ *
+ * Retrieve the security descriptor that is associated with the given file.
+ *
+ * PARAMS
+ *     lpFileName [I] Name of the file
+ *
+ * RETURNS
+ *     Success: ERROR_SUCCESS
+ *     Failure: other
+ */
+DWORD WINAPI RetreiveFileSecurity(LPCWSTR lpFileName,
+                                  PSECURITY_DESCRIPTOR *pSecurityDescriptor)
+{
+    PSECURITY_DESCRIPTOR SecDesc;
+    DWORD dwSize = 0x100;
+    DWORD dwError;
+
+    SecDesc = (PSECURITY_DESCRIPTOR)MyMalloc(dwSize);
+    if (SecDesc == NULL)
+        return ERROR_NOT_ENOUGH_MEMORY;
+
+    if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
+                         GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+                         SecDesc, dwSize, &dwSize))
+    {
+      *pSecurityDescriptor = SecDesc;
+      return ERROR_SUCCESS;
+    }
+
+    dwError = GetLastError();
+    if (dwError != ERROR_INSUFFICIENT_BUFFER)
+    {
+        MyFree(SecDesc);
+        return dwError;
+    }
+
+    SecDesc = (PSECURITY_DESCRIPTOR)MyRealloc(SecDesc, dwSize);
+    if (SecDesc == NULL)
+        return ERROR_NOT_ENOUGH_MEMORY;
+
+    if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
+                         GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+                         SecDesc, dwSize, &dwSize))
+    {
+      *pSecurityDescriptor = SecDesc;
+      return ERROR_SUCCESS;
+    }
+
+    dwError = GetLastError();
+    MyFree(SecDesc);
+
+    return dwError;
+}
diff --git a/dlls/setupapi/setupapi.spec b/dlls/setupapi/setupapi.spec
index 8e6f51d..4529a5e 100644
--- a/dlls/setupapi/setupapi.spec
+++ b/dlls/setupapi/setupapi.spec
@@ -190,8 +190,8 @@
 @ stub CM_Unregister_Device_InterfaceW
 @ stub CM_Unregister_Device_Interface_ExA
 @ stub CM_Unregister_Device_Interface_ExW
-@ stub CaptureAndConvertAnsiArg
-@ stub CaptureStringArg
+@ stdcall CaptureAndConvertAnsiArg(str ptr)
+@ stdcall CaptureStringArg(wstr ptr)
 @ stub CenterWindowRelativeToParent
 @ stub ConcatenatePaths
 @ stdcall DelayedMove(wstr wstr)
@@ -223,13 +223,13 @@
 @ stub MyGetFileTitle
 @ stdcall MyMalloc(long)
 @ stdcall MyRealloc(ptr long)
-@ stub OpenAndMapFileForRead
+@ stdcall OpenAndMapFileForRead(wstr ptr ptr ptr ptr)
 @ stub OutOfMemory
 @ stub QueryMultiSzValueToArray
 @ stdcall QueryRegistryValue(long wstr ptr ptr ptr)
 @ stub ReadAsciiOrUnicodeTextFile
 @ stub RegistryDelnode
-@ stub RetreiveFileSecurity
+@ stdcall RetreiveFileSecurity(wstr ptr)
 @ stub RetrieveServiceConfig
 @ stub SearchForInfFile
 @ stub SetArrayToMultiSzValue
@@ -512,7 +512,7 @@
 @ stdcall SetupTermDefaultQueueCallback(ptr)
 @ stdcall SetupTerminateFileLog(long)
 @ stub ShouldDeviceBeExcluded
-@ stub StampFileSecurity
+@ stdcall StampFileSecurity(wstr ptr)
 @ stub StringTableAddString
 @ stub StringTableAddStringEx
 @ stub StringTableDestroy
@@ -526,9 +526,9 @@
 @ stub StringTableSetExtraData
 @ stub StringTableStringFromId
 @ stub StringTableTrim
-@ stub TakeOwnershipOfFile
+@ stdcall TakeOwnershipOfFile(wstr)
 @ stdcall UnicodeToMultiByte(wstr long)
-@ stub UnmapAndCloseFile
+@ stdcall UnmapAndCloseFile(long long ptr)
 @ stub VerifyCatalogFile
 @ stub VerifyFile
 @ stub pSetupAccessRunOnceNodeList
diff --git a/include/setupapi.h b/include/setupapi.h
index cee5f4c..a5c5d1d 100644
--- a/include/setupapi.h
+++ b/include/setupapi.h
@@ -666,6 +666,8 @@
 
 
 LONG     WINAPI AddTagToGroupOrderList(PCWSTR lpGroupName, DWORD dwUnknown2, DWORD dwUnknown3);
+DWORD    WINAPI CaptureAndConvertAnsiArg(PCSTR lpSrc, PWSTR *lpDst);
+DWORD    WINAPI CaptureStringArg(PCWSTR lpSrc, PWSTR *lpDst);
 BOOL     WINAPI DelayedMove(PCWSTR lpExistingFileName, PCWSTR lpNewFileName);
 BOOL     WINAPI DoesUserHavePrivilege(PCWSTR lpPrivilegeName);
 PWSTR    WINAPI DuplicateString(PCWSTR lpSrc);
@@ -679,7 +681,9 @@
 VOID     WINAPI MyFree(PVOID lpMem);
 PVOID    WINAPI MyMalloc(DWORD dwSize);
 PVOID    WINAPI MyRealloc(PVOID lpSrc, DWORD dwSize);
+DWORD    WINAPI OpenAndMapForRead(PCWSTR, PDWORD, PHANDLE, PHANDLE, PVOID *);
 LONG     WINAPI QueryRegistryValue(HKEY, PCWSTR, PBYTE *, PDWORD, PDWORD);
+DWORD    WINAPI RetreiveFileSecurity(PCWSTR, PSECURITY_DESCRIPTOR *);
 BOOL     WINAPI SetupCloseFileQueue( HSPFILEQ );
 void     WINAPI SetupCloseInfFile( HINF hinf );
 BOOL     WINAPI SetupCommitFileQueueA( HWND, HSPFILEQ, PSP_FILE_CALLBACK_A, PVOID );
@@ -818,7 +822,11 @@
 #define         SetupSetFileQueueAlternatePlatform WINELIB_NAME_AW(SetupSetFileQueueAlternatePlatform)
 BOOL     WINAPI SetupSetFileQueueFlags( HSPFILEQ, DWORD, DWORD );
 void     WINAPI SetupTermDefaultQueueCallback( PVOID );
+DWORD    WINAPI StampFileSecurity(PCWSTR, PSECURITY_DESCRIPTOR);
+DWORD    WINAPI TakeOwnershipOfFile(PCWSTR);
 PSTR     WINAPI UnicodeToMultiByte(PCWSTR lpUnicodeStr, UINT uCodePage);
+BOOL     WINAPI UnmapAndCloseFile(HANDLE, HANDLE, PVOID);
+
 
 #undef DECL_WINELIB_SETUPAPI_TYPE_AW
 
diff --git a/include/winnt.h b/include/winnt.h
index d8a99d9..b0deea0 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -3040,7 +3040,7 @@
 
 typedef struct _TOKEN_OWNER {
   PSID Owner;
-} TOKEN_OWNER;
+} TOKEN_OWNER, *PTOKEN_OWNER;
 
 /*
  * TOKEN_PRIMARY_GROUP