ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

misc.c
Go to the documentation of this file.
00001 /*
00002  * Setupapi miscellaneous functions
00003  *
00004  * Copyright 2005 Eric Kohl
00005  * Copyright 2007 Hans Leidekker
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include "setupapi_private.h"
00023 
00024 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
00025 
00026 /* Unicode constants */
00027 static const WCHAR BackSlash[] = {'\\',0};
00028 static const WCHAR TranslationRegKey[] = {'\\','V','e','r','F','i','l','e','I','n','f','o','\\','T','r','a','n','s','l','a','t','i','o','n',0};
00029 
00030 DWORD
00031 GetFunctionPointer(
00032     IN PWSTR InstallerName,
00033     OUT HMODULE* ModulePointer,
00034     OUT PVOID* FunctionPointer)
00035 {
00036     HMODULE hModule = NULL;
00037     LPSTR FunctionNameA = NULL;
00038     PWCHAR Comma;
00039     DWORD rc;
00040 
00041     *ModulePointer = NULL;
00042     *FunctionPointer = NULL;
00043 
00044     Comma = strchrW(InstallerName, ',');
00045     if (!Comma)
00046     {
00047         rc = ERROR_INVALID_PARAMETER;
00048         goto cleanup;
00049     }
00050 
00051     /* Load library */
00052     *Comma = '\0';
00053     hModule = LoadLibraryW(InstallerName);
00054     *Comma = ',';
00055     if (!hModule)
00056     {
00057         rc = GetLastError();
00058         goto cleanup;
00059     }
00060 
00061     /* Skip comma spaces */
00062     while (*Comma == ',' || isspaceW(*Comma))
00063         Comma++;
00064 
00065     /* W->A conversion for function name */
00066     FunctionNameA = pSetupUnicodeToMultiByte(Comma, CP_ACP);
00067     if (!FunctionNameA)
00068     {
00069         rc = GetLastError();
00070         goto cleanup;
00071     }
00072 
00073     /* Search function */
00074     *FunctionPointer = GetProcAddress(hModule, FunctionNameA);
00075     if (!*FunctionPointer)
00076     {
00077         rc = GetLastError();
00078         goto cleanup;
00079     }
00080 
00081     *ModulePointer = hModule;
00082     rc = ERROR_SUCCESS;
00083 
00084 cleanup:
00085     if (rc != ERROR_SUCCESS && hModule)
00086         FreeLibrary(hModule);
00087     MyFree(FunctionNameA);
00088     return rc;
00089 }
00090 
00091 DWORD
00092 FreeFunctionPointer(
00093     IN HMODULE ModulePointer,
00094     IN PVOID FunctionPointer)
00095 {
00096     if (ModulePointer == NULL)
00097         return ERROR_SUCCESS;
00098     if (FreeLibrary(ModulePointer))
00099        return ERROR_SUCCESS;
00100     else
00101        return GetLastError();
00102 }
00103 
00104 /**************************************************************************
00105  * MyFree [SETUPAPI.@]
00106  *
00107  * Frees an allocated memory block from the process heap.
00108  *
00109  * PARAMS
00110  *     lpMem [I] pointer to memory block which will be freed
00111  *
00112  * RETURNS
00113  *     None
00114  */
00115 VOID WINAPI MyFree(LPVOID lpMem)
00116 {
00117     TRACE("%p\n", lpMem);
00118     HeapFree(GetProcessHeap(), 0, lpMem);
00119 }
00120 
00121 
00122 /**************************************************************************
00123  * MyMalloc [SETUPAPI.@]
00124  *
00125  * Allocates memory block from the process heap.
00126  *
00127  * PARAMS
00128  *     dwSize [I] size of the allocated memory block
00129  *
00130  * RETURNS
00131  *     Success: pointer to allocated memory block
00132  *     Failure: NULL
00133  */
00134 LPVOID WINAPI MyMalloc(DWORD dwSize)
00135 {
00136     TRACE("%lu\n", dwSize);
00137     return HeapAlloc(GetProcessHeap(), 0, dwSize);
00138 }
00139 
00140 
00141 /**************************************************************************
00142  * MyRealloc [SETUPAPI.@]
00143  *
00144  * Changes the size of an allocated memory block or allocates a memory
00145  * block from the process heap.
00146  *
00147  * PARAMS
00148  *     lpSrc  [I] pointer to memory block which will be resized
00149  *     dwSize [I] new size of the memory block
00150  *
00151  * RETURNS
00152  *     Success: pointer to the resized memory block
00153  *     Failure: NULL
00154  *
00155  * NOTES
00156  *     If lpSrc is a NULL-pointer, then MyRealloc allocates a memory
00157  *     block like MyMalloc.
00158  */
00159 LPVOID WINAPI MyRealloc(LPVOID lpSrc, DWORD dwSize)
00160 {
00161     TRACE("%p %lu\n", lpSrc, dwSize);
00162 
00163     if (lpSrc == NULL)
00164         return HeapAlloc(GetProcessHeap(), 0, dwSize);
00165 
00166     return HeapReAlloc(GetProcessHeap(), 0, lpSrc, dwSize);
00167 }
00168 
00169 
00170 /**************************************************************************
00171  * pSetupDuplicateString [SETUPAPI.@]
00172  *
00173  * Duplicates a unicode string.
00174  *
00175  * PARAMS
00176  *     lpSrc  [I] pointer to the unicode string that will be duplicated
00177  *
00178  * RETURNS
00179  *     Success: pointer to the duplicated unicode string
00180  *     Failure: NULL
00181  *
00182  * NOTES
00183  *     Call MyFree() to release the duplicated string.
00184  */
00185 LPWSTR WINAPI pSetupDuplicateString(LPCWSTR lpSrc)
00186 {
00187     LPWSTR lpDst;
00188 
00189     TRACE("%s\n", debugstr_w(lpSrc));
00190 
00191     lpDst = MyMalloc((lstrlenW(lpSrc) + 1) * sizeof(WCHAR));
00192     if (lpDst == NULL)
00193         return NULL;
00194 
00195     strcpyW(lpDst, lpSrc);
00196 
00197     return lpDst;
00198 }
00199 
00200 
00201 /**************************************************************************
00202  * QueryRegistryValue [SETUPAPI.@]
00203  *
00204  * Retrieves value data from the registry and allocates memory for the
00205  * value data.
00206  *
00207  * PARAMS
00208  *     hKey        [I] Handle of the key to query
00209  *     lpValueName [I] Name of value under hkey to query
00210  *     lpData      [O] Destination for the values contents,
00211  *     lpType      [O] Destination for the value type
00212  *     lpcbData    [O] Destination for the size of data
00213  *
00214  * RETURNS
00215  *     Success: ERROR_SUCCESS
00216  *     Failure: Otherwise
00217  *
00218  * NOTES
00219  *     Use MyFree to release the lpData buffer.
00220  */
00221 LONG WINAPI QueryRegistryValue(HKEY hKey,
00222                                LPCWSTR lpValueName,
00223                                LPBYTE  *lpData,
00224                                LPDWORD lpType,
00225                                LPDWORD lpcbData)
00226 {
00227     LONG lError;
00228 
00229     TRACE("%p %s %p %p %p\n",
00230           hKey, debugstr_w(lpValueName), lpData, lpType, lpcbData);
00231 
00232     /* Get required buffer size */
00233     *lpcbData = 0;
00234     lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, NULL, lpcbData);
00235     if (lError != ERROR_SUCCESS)
00236         return lError;
00237 
00238     /* Allocate buffer */
00239     *lpData = MyMalloc(*lpcbData);
00240     if (*lpData == NULL)
00241         return ERROR_NOT_ENOUGH_MEMORY;
00242 
00243     /* Query registry value */
00244     lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, *lpData, lpcbData);
00245     if (lError != ERROR_SUCCESS)
00246         MyFree(*lpData);
00247 
00248     return lError;
00249 }
00250 
00251 
00252 /**************************************************************************
00253  * pSetupMultiByteToUnicode [SETUPAPI.@]
00254  *
00255  * Converts a multi-byte string to a Unicode string.
00256  *
00257  * PARAMS
00258  *     lpMultiByteStr  [I] Multi-byte string to be converted
00259  *     uCodePage       [I] Code page
00260  *
00261  * RETURNS
00262  *     Success: pointer to the converted Unicode string
00263  *     Failure: NULL
00264  *
00265  * NOTE
00266  *     Use MyFree to release the returned Unicode string.
00267  */
00268 LPWSTR WINAPI pSetupMultiByteToUnicode(LPCSTR lpMultiByteStr, UINT uCodePage)
00269 {
00270     LPWSTR lpUnicodeStr;
00271     int nLength;
00272 
00273     TRACE("%s %d\n", debugstr_a(lpMultiByteStr), uCodePage);
00274 
00275     nLength = MultiByteToWideChar(uCodePage, 0, lpMultiByteStr,
00276                                   -1, NULL, 0);
00277     if (nLength == 0)
00278         return NULL;
00279 
00280     lpUnicodeStr = MyMalloc(nLength * sizeof(WCHAR));
00281     if (lpUnicodeStr == NULL)
00282     {
00283         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00284         return NULL;
00285     }
00286 
00287     if (!MultiByteToWideChar(uCodePage, 0, lpMultiByteStr,
00288                              nLength, lpUnicodeStr, nLength))
00289     {
00290         MyFree(lpUnicodeStr);
00291         return NULL;
00292     }
00293 
00294     return lpUnicodeStr;
00295 }
00296 
00297 
00298 /**************************************************************************
00299  * pSetupUnicodeToMultiByte [SETUPAPI.@]
00300  *
00301  * Converts a Unicode string to a multi-byte string.
00302  *
00303  * PARAMS
00304  *     lpUnicodeStr  [I] Unicode string to be converted
00305  *     uCodePage     [I] Code page
00306  *
00307  * RETURNS
00308  *     Success: pointer to the converted multi-byte string
00309  *     Failure: NULL
00310  *
00311  * NOTE
00312  *     Use MyFree to release the returned multi-byte string.
00313  */
00314 LPSTR WINAPI pSetupUnicodeToMultiByte(LPCWSTR lpUnicodeStr, UINT uCodePage)
00315 {
00316     LPSTR lpMultiByteStr;
00317     int nLength;
00318 
00319     TRACE("%s %d\n", debugstr_w(lpUnicodeStr), uCodePage);
00320 
00321     nLength = WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1,
00322                                   NULL, 0, NULL, NULL);
00323     if (nLength == 0)
00324         return NULL;
00325 
00326     lpMultiByteStr = MyMalloc(nLength);
00327     if (lpMultiByteStr == NULL)
00328         return NULL;
00329 
00330     if (!WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1,
00331                              lpMultiByteStr, nLength, NULL, NULL))
00332     {
00333         MyFree(lpMultiByteStr);
00334         return NULL;
00335     }
00336 
00337     return lpMultiByteStr;
00338 }
00339 
00340 
00341 /**************************************************************************
00342  * DoesUserHavePrivilege [SETUPAPI.@]
00343  *
00344  * Check whether the current user has got a given privilege.
00345  *
00346  * PARAMS
00347  *     lpPrivilegeName  [I] Name of the privilege to be checked
00348  *
00349  * RETURNS
00350  *     Success: TRUE
00351  *     Failure: FALSE
00352  */
00353 BOOL WINAPI DoesUserHavePrivilege(LPCWSTR lpPrivilegeName)
00354 {
00355     HANDLE hToken;
00356     DWORD dwSize;
00357     PTOKEN_PRIVILEGES lpPrivileges;
00358     LUID PrivilegeLuid;
00359     DWORD i;
00360     BOOL bResult = FALSE;
00361 
00362     TRACE("%s\n", debugstr_w(lpPrivilegeName));
00363 
00364     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
00365         return FALSE;
00366 
00367     if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize))
00368     {
00369         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
00370         {
00371             CloseHandle(hToken);
00372             return FALSE;
00373         }
00374     }
00375 
00376     lpPrivileges = MyMalloc(dwSize);
00377     if (lpPrivileges == NULL)
00378     {
00379         CloseHandle(hToken);
00380         return FALSE;
00381     }
00382 
00383     if (!GetTokenInformation(hToken, TokenPrivileges, lpPrivileges, dwSize, &dwSize))
00384     {
00385         MyFree(lpPrivileges);
00386         CloseHandle(hToken);
00387         return FALSE;
00388     }
00389 
00390     CloseHandle(hToken);
00391 
00392     if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, &PrivilegeLuid))
00393     {
00394         MyFree(lpPrivileges);
00395         return FALSE;
00396     }
00397 
00398     for (i = 0; i < lpPrivileges->PrivilegeCount; i++)
00399     {
00400         if (lpPrivileges->Privileges[i].Luid.HighPart == PrivilegeLuid.HighPart &&
00401             lpPrivileges->Privileges[i].Luid.LowPart == PrivilegeLuid.LowPart)
00402         {
00403             bResult = TRUE;
00404         }
00405     }
00406 
00407     MyFree(lpPrivileges);
00408 
00409     return bResult;
00410 }
00411 
00412 
00413 /**************************************************************************
00414  * pSetupEnablePrivilege [SETUPAPI.@]
00415  *
00416  * Enables or disables one of the current users privileges.
00417  *
00418  * PARAMS
00419  *     lpPrivilegeName  [I] Name of the privilege to be changed
00420  *     bEnable          [I] TRUE: Enables the privilege
00421  *                          FALSE: Disables the privilege
00422  *
00423  * RETURNS
00424  *     Success: TRUE
00425  *     Failure: FALSE
00426  */
00427 BOOL WINAPI pSetupEnablePrivilege(LPCWSTR lpPrivilegeName, BOOL bEnable)
00428 {
00429     TOKEN_PRIVILEGES Privileges;
00430     HANDLE hToken;
00431     BOOL bResult;
00432 
00433     TRACE("%s %s\n", debugstr_w(lpPrivilegeName), bEnable ? "TRUE" : "FALSE");
00434 
00435     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
00436         return FALSE;
00437 
00438     Privileges.PrivilegeCount = 1;
00439     Privileges.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;
00440 
00441     if (!LookupPrivilegeValueW(NULL, lpPrivilegeName,
00442                                &Privileges.Privileges[0].Luid))
00443     {
00444         CloseHandle(hToken);
00445         return FALSE;
00446     }
00447 
00448     bResult = AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL);
00449 
00450     CloseHandle(hToken);
00451 
00452     return bResult;
00453 }
00454 
00455 
00456 /**************************************************************************
00457  * DelayedMove [SETUPAPI.@]
00458  *
00459  * Moves a file upon the next reboot.
00460  *
00461  * PARAMS
00462  *     lpExistingFileName  [I] Current file name
00463  *     lpNewFileName       [I] New file name
00464  *
00465  * RETURNS
00466  *     Success: TRUE
00467  *     Failure: FALSE
00468  */
00469 BOOL WINAPI DelayedMove(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
00470 {
00471     return MoveFileExW(lpExistingFileName, lpNewFileName,
00472                        MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT);
00473 }
00474 
00475 
00476 /**************************************************************************
00477  * FileExists [SETUPAPI.@]
00478  *
00479  * Checks whether a file exists.
00480  *
00481  * PARAMS
00482  *     lpFileName     [I] Name of the file to check
00483  *     lpNewFileName  [O] Optional information about the existing file
00484  *
00485  * RETURNS
00486  *     Success: TRUE
00487  *     Failure: FALSE
00488  */
00489 BOOL WINAPI FileExists(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFileFindData)
00490 {
00491     WIN32_FIND_DATAW FindData;
00492     HANDLE hFind;
00493     UINT uErrorMode;
00494     DWORD dwError;
00495 
00496     uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
00497 
00498     hFind = FindFirstFileW(lpFileName, &FindData);
00499     if (hFind == INVALID_HANDLE_VALUE)
00500     {
00501         dwError = GetLastError();
00502         SetErrorMode(uErrorMode);
00503         SetLastError(dwError);
00504         return FALSE;
00505     }
00506 
00507     FindClose(hFind);
00508 
00509     if (lpFileFindData)
00510         memcpy(lpFileFindData, &FindData, sizeof(WIN32_FIND_DATAW));
00511 
00512     SetErrorMode(uErrorMode);
00513 
00514     return TRUE;
00515 }
00516 
00517 
00518 /**************************************************************************
00519  * CaptureStringArg [SETUPAPI.@]
00520  *
00521  * Captures a UNICODE string.
00522  *
00523  * PARAMS
00524  *     lpSrc  [I] UNICODE string to be captured
00525  *     lpDst  [O] Pointer to the captured UNICODE string
00526  *
00527  * RETURNS
00528  *     Success: ERROR_SUCCESS
00529  *     Failure: ERROR_INVALID_PARAMETER
00530  *
00531  * NOTE
00532  *     Call MyFree to release the captured UNICODE string.
00533  */
00534 DWORD WINAPI CaptureStringArg(LPCWSTR pSrc, LPWSTR *pDst)
00535 {
00536     if (pDst == NULL)
00537         return ERROR_INVALID_PARAMETER;
00538 
00539     *pDst = pSetupDuplicateString(pSrc);
00540 
00541     return ERROR_SUCCESS;
00542 }
00543 
00544 
00545 /**************************************************************************
00546  * pSetupCaptureAndConvertAnsiArg [SETUPAPI.@]
00547  *
00548  * Captures an ANSI string and converts it to a UNICODE string.
00549  *
00550  * PARAMS
00551  *     lpSrc  [I] ANSI string to be captured
00552  *     lpDst  [O] Pointer to the captured UNICODE string
00553  *
00554  * RETURNS
00555  *     Success: ERROR_SUCCESS
00556  *     Failure: ERROR_INVALID_PARAMETER
00557  *
00558  * NOTE
00559  *     Call MyFree to release the captured UNICODE string.
00560  */
00561 DWORD WINAPI pSetupCaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst)
00562 {
00563     if (pDst == NULL)
00564         return ERROR_INVALID_PARAMETER;
00565 
00566     *pDst = pSetupMultiByteToUnicode(pSrc, CP_ACP);
00567 
00568     return ERROR_SUCCESS;
00569 }
00570 
00571 
00572 /**************************************************************************
00573  * pSetupOpenAndMapFileForRead [SETUPAPI.@]
00574  *
00575  * Open and map a file to a buffer.
00576  *
00577  * PARAMS
00578  *     lpFileName [I] Name of the file to be opened
00579  *     lpSize     [O] Pointer to the file size
00580  *     lpFile     [0] Pointer to the file handle
00581  *     lpMapping  [0] Pointer to the mapping handle
00582  *     lpBuffer   [0] Pointer to the file buffer
00583  *
00584  * RETURNS
00585  *     Success: ERROR_SUCCESS
00586  *     Failure: Other
00587  *
00588  * NOTE
00589  *     Call UnmapAndCloseFile to release the file.
00590  */
00591 DWORD WINAPI pSetupOpenAndMapFileForRead(LPCWSTR lpFileName,
00592                                          LPDWORD lpSize,
00593                                          LPHANDLE lpFile,
00594                                          LPHANDLE lpMapping,
00595                                          LPVOID *lpBuffer)
00596 {
00597     DWORD dwError;
00598 
00599     TRACE("%s %p %p %p %p\n",
00600           debugstr_w(lpFileName), lpSize, lpFile, lpMapping, lpBuffer);
00601 
00602     *lpFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
00603                           OPEN_EXISTING, 0, NULL);
00604     if (*lpFile == INVALID_HANDLE_VALUE)
00605         return GetLastError();
00606 
00607     *lpSize = GetFileSize(*lpFile, NULL);
00608     if (*lpSize == INVALID_FILE_SIZE)
00609     {
00610         dwError = GetLastError();
00611         CloseHandle(*lpFile);
00612         return dwError;
00613     }
00614 
00615     *lpMapping = CreateFileMappingW(*lpFile, NULL, PAGE_READONLY, 0,
00616                                     *lpSize, NULL);
00617     if (*lpMapping == NULL)
00618     {
00619         dwError = GetLastError();
00620         CloseHandle(*lpFile);
00621         return dwError;
00622     }
00623 
00624     *lpBuffer = MapViewOfFile(*lpMapping, FILE_MAP_READ, 0, 0, *lpSize);
00625     if (*lpBuffer == NULL)
00626     {
00627         dwError = GetLastError();
00628         CloseHandle(*lpMapping);
00629         CloseHandle(*lpFile);
00630         return dwError;
00631     }
00632 
00633     return ERROR_SUCCESS;
00634 }
00635 
00636 
00637 /**************************************************************************
00638  * pSetupUnmapAndCloseFile [SETUPAPI.@]
00639  *
00640  * Unmap and close a mapped file.
00641  *
00642  * PARAMS
00643  *     hFile    [I] Handle to the file
00644  *     hMapping [I] Handle to the file mapping
00645  *     lpBuffer [I] Pointer to the file buffer
00646  *
00647  * RETURNS
00648  *     Success: TRUE
00649  *     Failure: FALSE
00650  */
00651 BOOL WINAPI pSetupUnmapAndCloseFile(HANDLE hFile, HANDLE hMapping, LPVOID lpBuffer)
00652 {
00653     TRACE("%p %p %p\n",
00654           hFile, hMapping, lpBuffer);
00655 
00656     if (!UnmapViewOfFile(lpBuffer))
00657         return FALSE;
00658 
00659     if (!CloseHandle(hMapping))
00660         return FALSE;
00661 
00662     if (!CloseHandle(hFile))
00663         return FALSE;
00664 
00665     return TRUE;
00666 }
00667 
00668 
00669 /**************************************************************************
00670  * StampFileSecurity [SETUPAPI.@]
00671  *
00672  * Assign a new security descriptor to the given file.
00673  *
00674  * PARAMS
00675  *     lpFileName          [I] Name of the file
00676  *     pSecurityDescriptor [I] New security descriptor
00677  *
00678  * RETURNS
00679  *     Success: ERROR_SUCCESS
00680  *     Failure: other
00681  */
00682 DWORD WINAPI StampFileSecurity(LPCWSTR lpFileName, PSECURITY_DESCRIPTOR pSecurityDescriptor)
00683 {
00684     TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor);
00685 
00686     if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
00687                           GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
00688                           pSecurityDescriptor))
00689         return GetLastError();
00690 
00691     return ERROR_SUCCESS;
00692 }
00693 
00694 
00695 /**************************************************************************
00696  * TakeOwnershipOfFile [SETUPAPI.@]
00697  *
00698  * Takes the ownership of the given file.
00699  *
00700  * PARAMS
00701  *     lpFileName [I] Name of the file
00702  *
00703  * RETURNS
00704  *     Success: ERROR_SUCCESS
00705  *     Failure: other
00706  */
00707 DWORD WINAPI TakeOwnershipOfFile(LPCWSTR lpFileName)
00708 {
00709     SECURITY_DESCRIPTOR SecDesc;
00710     HANDLE hToken = NULL;
00711     PTOKEN_OWNER pOwner = NULL;
00712     DWORD dwError;
00713     DWORD dwSize;
00714 
00715     TRACE("%s\n", debugstr_w(lpFileName));
00716 
00717     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
00718         return GetLastError();
00719 
00720     if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &dwSize))
00721     {
00722         goto fail;
00723     }
00724 
00725     pOwner = (PTOKEN_OWNER)MyMalloc(dwSize);
00726     if (pOwner == NULL)
00727     {
00728         CloseHandle(hToken);
00729         return ERROR_NOT_ENOUGH_MEMORY;
00730     }
00731 
00732     if (!GetTokenInformation(hToken, TokenOwner, pOwner, dwSize, &dwSize))
00733     {
00734         goto fail;
00735     }
00736 
00737     if (!InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION))
00738     {
00739         goto fail;
00740     }
00741 
00742     if (!SetSecurityDescriptorOwner(&SecDesc, pOwner->Owner, FALSE))
00743     {
00744         goto fail;
00745     }
00746 
00747     if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, &SecDesc))
00748     {
00749         goto fail;
00750     }
00751 
00752     MyFree(pOwner);
00753     CloseHandle(hToken);
00754 
00755     return ERROR_SUCCESS;
00756 
00757 fail:;
00758     dwError = GetLastError();
00759 
00760     MyFree(pOwner);
00761 
00762     if (hToken != NULL)
00763         CloseHandle(hToken);
00764 
00765     return dwError;
00766 }
00767 
00768 
00769 /**************************************************************************
00770  * RetreiveFileSecurity [SETUPAPI.@]
00771  *
00772  * Retrieve the security descriptor that is associated with the given file.
00773  *
00774  * PARAMS
00775  *     lpFileName [I] Name of the file
00776  *
00777  * RETURNS
00778  *     Success: ERROR_SUCCESS
00779  *     Failure: other
00780  */
00781 DWORD WINAPI RetreiveFileSecurity(LPCWSTR lpFileName,
00782                                   PSECURITY_DESCRIPTOR *pSecurityDescriptor)
00783 {
00784     PSECURITY_DESCRIPTOR SecDesc;
00785     DWORD dwSize = 0x100;
00786     DWORD dwError;
00787 
00788     TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor);
00789 
00790     SecDesc = MyMalloc(dwSize);
00791     if (SecDesc == NULL)
00792         return ERROR_NOT_ENOUGH_MEMORY;
00793 
00794     if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
00795                          GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
00796                          SecDesc, dwSize, &dwSize))
00797     {
00798       *pSecurityDescriptor = SecDesc;
00799       return ERROR_SUCCESS;
00800     }
00801 
00802     dwError = GetLastError();
00803     if (dwError != ERROR_INSUFFICIENT_BUFFER)
00804     {
00805         MyFree(SecDesc);
00806         return dwError;
00807     }
00808 
00809     SecDesc = MyRealloc(SecDesc, dwSize);
00810     if (SecDesc == NULL)
00811         return ERROR_NOT_ENOUGH_MEMORY;
00812 
00813     if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
00814                          GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
00815                          SecDesc, dwSize, &dwSize))
00816     {
00817       *pSecurityDescriptor = SecDesc;
00818       return ERROR_SUCCESS;
00819     }
00820 
00821     dwError = GetLastError();
00822     MyFree(SecDesc);
00823 
00824     return dwError;
00825 }
00826 
00827 
00828 static DWORD global_flags = 0;  /* FIXME: what should be in here? */
00829 
00830 /***********************************************************************
00831  *      pSetupGetGlobalFlags  (SETUPAPI.@)
00832  */
00833 DWORD WINAPI pSetupGetGlobalFlags(void)
00834 {
00835     FIXME( "stub\n" );
00836     return global_flags;
00837 }
00838 
00839 
00840 /***********************************************************************
00841  *      pSetupSetGlobalFlags  (SETUPAPI.@)
00842  */
00843 void WINAPI pSetupSetGlobalFlags( DWORD flags )
00844 {
00845     global_flags = flags;
00846 }
00847 
00848 /***********************************************************************
00849  *              AssertFail  (SETUPAPI.@)
00850  *
00851  * Shows an assert fail error messagebox
00852  *
00853  * PARAMS
00854  *   lpFile [I]         file where assert failed
00855  *   uLine [I]          line number in file
00856  *   lpMessage [I]      assert message
00857  *
00858  */
00859 VOID WINAPI AssertFail(LPSTR lpFile, UINT uLine, LPSTR lpMessage)
00860 {
00861     CHAR szModule[MAX_PATH];
00862     CHAR szBuffer[2048];
00863     LPSTR lpName;
00864 //    LPSTR lpBuffer;
00865 
00866     TRACE("%s %u %s\n", lpFile, uLine, lpMessage);
00867 
00868     GetModuleFileNameA(hInstance, szModule, MAX_PATH);
00869     lpName = strrchr(szModule, '\\');
00870     if (lpName != NULL)
00871         lpName++;
00872     else
00873         lpName = szModule;
00874 
00875     wsprintfA(szBuffer,
00876               "Assertion failure at line %u in file %s: %s\n\nCall DebugBreak()?",
00877               uLine, lpFile, lpMessage);
00878 
00879     if (MessageBoxA(NULL, szBuffer, lpName, MB_SETFOREGROUND |
00880                     MB_TASKMODAL | MB_ICONERROR | MB_YESNO) == IDYES)
00881         DebugBreak();
00882 }
00883 
00884 
00885 /**************************************************************************
00886  * GetSetFileTimestamp [SETUPAPI.@]
00887  *
00888  * Gets or sets a files timestamp.
00889  *
00890  * PARAMS
00891  *     lpFileName       [I]   File name
00892  *     lpCreationTime   [I/O] Creation time
00893  *     lpLastAccessTime [I/O] Last access time
00894  *     lpLastWriteTime  [I/O] Last write time
00895  *     bSetFileTime     [I]   TRUE: Set file times
00896  *                            FALSE: Get file times
00897  *
00898  * RETURNS
00899  *     Success: ERROR_SUCCESS
00900  *     Failure: other
00901  */
00902 DWORD WINAPI GetSetFileTimestamp(LPCWSTR lpFileName,
00903                                  LPFILETIME lpCreationTime,
00904                                  LPFILETIME lpLastAccessTime,
00905                                  LPFILETIME lpLastWriteTime,
00906                                  BOOLEAN bSetFileTime)
00907 {
00908     HANDLE hFile;
00909     BOOLEAN bRet;
00910     DWORD dwError = ERROR_SUCCESS;
00911 
00912     TRACE("%s %p %p %p %x\n", debugstr_w(lpFileName), lpCreationTime,
00913           lpLastAccessTime, lpLastWriteTime, bSetFileTime);
00914 
00915     hFile = CreateFileW(lpFileName,
00916                         bSetFileTime ? GENERIC_WRITE : GENERIC_READ,
00917                         FILE_SHARE_READ | FILE_SHARE_WRITE,
00918                         NULL,
00919                         OPEN_EXISTING,
00920                         0,
00921                         NULL);
00922 
00923     if (hFile == INVALID_HANDLE_VALUE)
00924         return GetLastError();
00925 
00926     if (bSetFileTime)
00927         bRet = SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
00928     else
00929         bRet = GetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
00930 
00931     if (bRet == FALSE)
00932         dwError = GetLastError();
00933 
00934      CloseHandle(hFile);
00935 
00936      return dwError;
00937 }
00938 
00939 
00940 /**************************************************************************
00941  * pSetupGetFileTitle [SETUPAPI.@]
00942  *
00943  * Returns a pointer to the last part of a fully qualified file name.
00944  *
00945  * PARAMS
00946  *     lpFileName [I] File name
00947  *
00948  * RETURNS
00949  *     Pointer to a files name.
00950  */
00951 LPWSTR WINAPI
00952 pSetupGetFileTitle(LPCWSTR lpFileName)
00953 {
00954     LPWSTR ptr;
00955     LPWSTR ret;
00956     WCHAR c;
00957 
00958     TRACE("%s\n", debugstr_w(lpFileName));
00959 
00960     ptr = (LPWSTR)lpFileName;
00961     ret = ptr;
00962     while (TRUE)
00963     {
00964         c = *ptr;
00965 
00966         if (c == 0)
00967             break;
00968 
00969         ptr++;
00970         if (c == (WCHAR)'\\' || c == (WCHAR)'/' || c == (WCHAR)':')
00971             ret = ptr;
00972     }
00973 
00974     return ret;
00975 }
00976 
00977 
00978 /**************************************************************************
00979  * pSetupConcatenatePaths [SETUPAPI.@]
00980  *
00981  * Concatenates two paths.
00982  *
00983  * PARAMS
00984  *     lpPath         [I/O] Path to append path to
00985  *     lpAppend       [I]   Path to append
00986  *     dwBufferSize   [I]   Size of the path buffer
00987  *     lpRequiredSize [O]   Required size for the concatenated path. Optional
00988  *
00989  * RETURNS
00990  *     Success: TRUE
00991  *     Failure: FALSE
00992  */
00993 BOOL WINAPI
00994 pSetupConcatenatePaths(LPWSTR lpPath,
00995                        LPCWSTR lpAppend,
00996                        DWORD dwBufferSize,
00997                        LPDWORD lpRequiredSize)
00998 {
00999     DWORD dwPathSize;
01000     DWORD dwAppendSize;
01001     DWORD dwTotalSize;
01002     BOOL bBackslash = FALSE;
01003 
01004     TRACE("%s %s %lu %p\n", debugstr_w(lpPath), debugstr_w(lpAppend),
01005           dwBufferSize, lpRequiredSize);
01006 
01007     dwPathSize = lstrlenW(lpPath);
01008 
01009     /* Ignore trailing backslash */
01010     if (lpPath[dwPathSize - 1] == (WCHAR)'\\')
01011         dwPathSize--;
01012 
01013     dwAppendSize = lstrlenW(lpAppend);
01014 
01015     /* Does the source string have a leading backslash? */
01016     if (lpAppend[0] == (WCHAR)'\\')
01017     {
01018         bBackslash = TRUE;
01019         dwAppendSize--;
01020     }
01021 
01022     dwTotalSize = dwPathSize + dwAppendSize + 2;
01023     if (lpRequiredSize != NULL)
01024         *lpRequiredSize = dwTotalSize;
01025 
01026     /* Append a backslash to the destination string */
01027     if (bBackslash == FALSE)
01028     {
01029         if (dwPathSize < dwBufferSize)
01030         {
01031             lpPath[dwPathSize - 1] = (WCHAR)'\\';
01032             dwPathSize++;
01033         }
01034     }
01035 
01036     if (dwPathSize + dwAppendSize < dwBufferSize)
01037     {
01038         lstrcpynW(&lpPath[dwPathSize],
01039                   lpAppend,
01040                   dwAppendSize);
01041     }
01042 
01043     if (dwBufferSize >= dwTotalSize)
01044         lpPath[dwTotalSize - 1] = 0;
01045 
01046     return (dwBufferSize >= dwTotalSize);
01047 }
01048 
01049 
01050 /**************************************************************************
01051  * pSetupCenterWindowRelativeToParent [SETUPAPI.@]
01052  *
01053  * Centers a window relative to its parent.
01054  *
01055  * PARAMS
01056  *     hwnd [I] Window to center.
01057  *
01058  * RETURNS
01059  *     None
01060  */
01061 VOID WINAPI
01062 pSetupCenterWindowRelativeToParent(HWND hwnd)
01063 {
01064     HWND hwndOwner;
01065     POINT ptOrigin;
01066     RECT rcWindow;
01067     RECT rcOwner;
01068     INT nWindowWidth, nWindowHeight;
01069     INT nOwnerWidth, nOwnerHeight;
01070     INT posX, posY;
01071 
01072     hwndOwner = GetWindow(hwnd, GW_OWNER);
01073     if (hwndOwner == NULL)
01074         return;
01075 
01076     ptOrigin.x = 0;
01077     ptOrigin.y = 0;
01078     ClientToScreen(hwndOwner, &ptOrigin);
01079 
01080     GetWindowRect(hwnd, &rcWindow);
01081     GetClientRect(hwndOwner, &rcOwner);
01082 
01083     nWindowWidth = rcWindow.right - rcWindow.left;
01084     nWindowHeight = rcWindow.bottom - rcWindow.top;
01085 
01086     nOwnerWidth = rcOwner.right - rcOwner.left;
01087     nOwnerHeight = rcOwner.bottom - rcOwner.top;
01088 
01089     posX = ((nOwnerWidth - nWindowWidth) / 2) + ptOrigin.x;
01090     posY = ((nOwnerHeight - nWindowHeight) / 2) + ptOrigin.y;
01091 
01092     MoveWindow(hwnd, posX, posY, nWindowHeight, nWindowWidth, 0);
01093 }
01094 
01095 
01096 /**************************************************************************
01097  * pSetupGetVersionInfoFromImage [SETUPAPI.@]
01098  *
01099  * Retrieves version information for a given file.
01100  *
01101  * PARAMS
01102  *     lpFileName       [I] File name
01103  *     lpFileVersion    [O] Pointer to the full file version
01104  *     lpVersionVarSize [O] Pointer to the size of the variable version
01105  *                          information
01106  *
01107  * RETURNS
01108  *     Success: TRUE
01109  *     Failure: FALSE
01110  */
01111 BOOL WINAPI
01112 pSetupGetVersionInfoFromImage(LPWSTR lpFileName,
01113                               PULARGE_INTEGER lpFileVersion,
01114                               LPWORD lpVersionVarSize)
01115 {
01116     DWORD dwHandle;
01117     DWORD dwSize;
01118     LPVOID lpInfo;
01119     UINT uSize;
01120     VS_FIXEDFILEINFO *lpFixedInfo;
01121     LPWORD lpVarSize;
01122 
01123     dwSize = GetFileVersionInfoSizeW(lpFileName, &dwHandle);
01124     if (dwSize == 0)
01125         return FALSE;
01126 
01127     lpInfo = MyMalloc(dwSize);
01128     if (lpInfo == NULL)
01129         return FALSE;
01130 
01131     if (!GetFileVersionInfoW(lpFileName, 0, dwSize, lpInfo))
01132     {
01133         MyFree(lpInfo);
01134         return FALSE;
01135     }
01136 
01137     if (!VerQueryValueW(lpInfo, BackSlash,
01138                         (LPVOID*)&lpFixedInfo, &uSize))
01139     {
01140         MyFree(lpInfo);
01141         return FALSE;
01142     }
01143 
01144     lpFileVersion->LowPart = lpFixedInfo->dwFileVersionLS;
01145     lpFileVersion->HighPart = lpFixedInfo->dwFileVersionMS;
01146 
01147     *lpVersionVarSize = 0;
01148     if (!VerQueryValueW(lpInfo, TranslationRegKey,
01149                         (LPVOID*)&lpVarSize, &uSize))
01150     {
01151         MyFree(lpInfo);
01152         return TRUE;
01153     }
01154 
01155     if (uSize >= 4)
01156     {
01157         *lpVersionVarSize = *lpVarSize;
01158     }
01159 
01160     MyFree(lpInfo);
01161 
01162     return TRUE;
01163 }
01164 
01165 /***********************************************************************
01166  *      SetupUninstallOEMInfW  (SETUPAPI.@)
01167  */
01168 BOOL WINAPI SetupUninstallOEMInfW( PCWSTR inf_file, DWORD flags, PVOID reserved )
01169 {
01170     static const WCHAR infW[] = {'\\','i','n','f','\\',0};
01171     WCHAR target[MAX_PATH];
01172 
01173     TRACE("%s, 0x%08x, %p\n", debugstr_w(inf_file), flags, reserved);
01174 
01175     if (!inf_file)
01176     {
01177         SetLastError(ERROR_INVALID_PARAMETER);
01178         return FALSE;
01179     }
01180 
01181     if (!GetWindowsDirectoryW( target, sizeof(target)/sizeof(WCHAR) )) return FALSE;
01182 
01183     strcatW( target, infW );
01184     strcatW( target, inf_file );
01185 
01186     if (flags & SUOI_FORCEDELETE)
01187         return DeleteFileW(target);
01188 
01189     FIXME("not deleting %s\n", debugstr_w(target));
01190 
01191     return TRUE;
01192 }
01193 
01194 /***********************************************************************
01195  *      SetupUninstallOEMInfA  (SETUPAPI.@)
01196  */
01197 BOOL WINAPI SetupUninstallOEMInfA( PCSTR inf_file, DWORD flags, PVOID reserved )
01198 {
01199     BOOL ret;
01200     WCHAR *inf_fileW = NULL;
01201 
01202     TRACE("%s, 0x%08x, %p\n", debugstr_a(inf_file), flags, reserved);
01203 
01204     if (inf_file && !(inf_fileW = strdupAtoW( inf_file ))) return FALSE;
01205     ret = SetupUninstallOEMInfW( inf_fileW, flags, reserved );
01206     HeapFree( GetProcessHeap(), 0, inf_fileW );
01207     return ret;
01208 }
01209 
01210 /***********************************************************************
01211  *      InstallCatalog  (SETUPAPI.@)
01212  */
01213 DWORD WINAPI InstallCatalog( LPCSTR catalog, LPCSTR basename, LPSTR fullname )
01214 {
01215     FIXME("%s, %s, %p\n", debugstr_a(catalog), debugstr_a(basename), fullname);
01216     return 0;
01217 }
01218 
01219 static UINT detect_compression_type( LPCWSTR file )
01220 {
01221     DWORD size;
01222     HANDLE handle;
01223     UINT type = FILE_COMPRESSION_NONE;
01224     static const BYTE LZ_MAGIC[] = { 0x53, 0x5a, 0x44, 0x44, 0x88, 0xf0, 0x27, 0x33 };
01225     static const BYTE MSZIP_MAGIC[] = { 0x4b, 0x57, 0x41, 0x4a };
01226     static const BYTE NTCAB_MAGIC[] = { 0x4d, 0x53, 0x43, 0x46 };
01227     BYTE buffer[8];
01228 
01229     handle = CreateFileW( file, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL );
01230     if (handle == INVALID_HANDLE_VALUE)
01231     {
01232         ERR("cannot open file %s\n", debugstr_w(file));
01233         return FILE_COMPRESSION_NONE;
01234     }
01235     if (!ReadFile( handle, buffer, sizeof(buffer), &size, NULL ) || size != sizeof(buffer))
01236     {
01237         CloseHandle( handle );
01238         return FILE_COMPRESSION_NONE;
01239     }
01240     if (!memcmp( buffer, LZ_MAGIC, sizeof(LZ_MAGIC) )) type = FILE_COMPRESSION_WINLZA;
01241     else if (!memcmp( buffer, MSZIP_MAGIC, sizeof(MSZIP_MAGIC) )) type = FILE_COMPRESSION_MSZIP;
01242     else if (!memcmp( buffer, NTCAB_MAGIC, sizeof(NTCAB_MAGIC) )) type = FILE_COMPRESSION_MSZIP; /* not a typo */
01243 
01244     CloseHandle( handle );
01245     return type;
01246 }
01247 
01248 static BOOL get_file_size( LPCWSTR file, DWORD *size )
01249 {
01250     HANDLE handle;
01251 
01252     handle = CreateFileW( file, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL );
01253     if (handle == INVALID_HANDLE_VALUE)
01254     {
01255         ERR("cannot open file %s\n", debugstr_w(file));
01256         return FALSE;
01257     }
01258     *size = GetFileSize( handle, NULL );
01259     CloseHandle( handle );
01260     return TRUE;
01261 }
01262 
01263 static BOOL get_file_sizes_none( LPCWSTR source, DWORD *source_size, DWORD *target_size )
01264 {
01265     DWORD size;
01266 
01267     if (!get_file_size( source, &size )) return FALSE;
01268     if (source_size) *source_size = size;
01269     if (target_size) *target_size = size;
01270     return TRUE;
01271 }
01272 
01273 static BOOL get_file_sizes_lz( LPCWSTR source, DWORD *source_size, DWORD *target_size )
01274 {
01275     DWORD size;
01276     BOOL ret = TRUE;
01277 
01278     if (source_size)
01279     {
01280         if (!get_file_size( source, &size )) ret = FALSE;
01281         else *source_size = size;
01282     }
01283     if (target_size)
01284     {
01285         INT file;
01286         OFSTRUCT of;
01287 
01288         if ((file = LZOpenFileW( (LPWSTR)source, &of, OF_READ )) < 0)
01289         {
01290             ERR("cannot open source file for reading\n");
01291             return FALSE;
01292         }
01293         *target_size = LZSeek( file, 0, 2 );
01294         LZClose( file );
01295     }
01296     return ret;
01297 }
01298 
01299 static UINT CALLBACK file_compression_info_callback( PVOID context, UINT notification, UINT_PTR param1, UINT_PTR param2 )
01300 {
01301     DWORD *size = context;
01302     FILE_IN_CABINET_INFO_W *info = (FILE_IN_CABINET_INFO_W *)param1;
01303 
01304     switch (notification)
01305     {
01306     case SPFILENOTIFY_FILEINCABINET:
01307     {
01308         *size = info->FileSize;
01309         return FILEOP_SKIP;
01310     }
01311     default: return NO_ERROR;
01312     }
01313 }
01314 
01315 static BOOL get_file_sizes_cab( LPCWSTR source, DWORD *source_size, DWORD *target_size )
01316 {
01317     DWORD size;
01318     BOOL ret = TRUE;
01319 
01320     if (source_size)
01321     {
01322         if (!get_file_size( source, &size )) ret = FALSE;
01323         else *source_size = size;
01324     }
01325     if (target_size)
01326     {
01327         ret = SetupIterateCabinetW( source, 0, file_compression_info_callback, target_size );
01328     }
01329     return ret;
01330 }
01331 
01332 /***********************************************************************
01333  *      SetupGetFileCompressionInfoExA  (SETUPAPI.@)
01334  *
01335  * See SetupGetFileCompressionInfoExW.
01336  */
01337 BOOL WINAPI SetupGetFileCompressionInfoExA( PCSTR source, PSTR name, DWORD len, PDWORD required,
01338                                             PDWORD source_size, PDWORD target_size, PUINT type )
01339 {
01340     BOOL ret;
01341     WCHAR *nameW = NULL, *sourceW = NULL;
01342     DWORD nb_chars = 0;
01343     LPSTR nameA;
01344 
01345     TRACE("%s, %p, %d, %p, %p, %p, %p\n", debugstr_a(source), name, len, required,
01346           source_size, target_size, type);
01347 
01348     if (!source || !(sourceW = pSetupMultiByteToUnicode( source, CP_ACP ))) return FALSE;
01349 
01350     if (name)
01351     {
01352         ret = SetupGetFileCompressionInfoExW( sourceW, NULL, 0, &nb_chars, NULL, NULL, NULL );
01353         if (!(nameW = HeapAlloc( GetProcessHeap(), 0, nb_chars * sizeof(WCHAR) )))
01354         {
01355             MyFree( sourceW );
01356             return FALSE;
01357         }
01358     }
01359     ret = SetupGetFileCompressionInfoExW( sourceW, nameW, nb_chars, &nb_chars, source_size, target_size, type );
01360     if (ret)
01361     {
01362         if ((nameA = pSetupUnicodeToMultiByte( nameW, CP_ACP )))
01363         {
01364             if (name && len >= nb_chars) lstrcpyA( name, nameA );
01365             else
01366             {
01367                 SetLastError( ERROR_INSUFFICIENT_BUFFER );
01368                 ret = FALSE;
01369             }
01370             MyFree( nameA );
01371         }
01372     }
01373     if (required) *required = nb_chars;
01374     HeapFree( GetProcessHeap(), 0, nameW );
01375     MyFree( sourceW );
01376 
01377     return ret;
01378 }
01379 
01380 /***********************************************************************
01381  *      SetupGetFileCompressionInfoExW  (SETUPAPI.@)
01382  *
01383  * Get compression type and compressed/uncompressed sizes of a given file.
01384  *
01385  * PARAMS
01386  *  source      [I] File to examine.
01387  *  name        [O] Actual filename used.
01388  *  len         [I] Length in characters of 'name' buffer.
01389  *  required    [O] Number of characters written to 'name'.
01390  *  source_size [O] Size of compressed file.
01391  *  target_size [O] Size of uncompressed file.
01392  *  type        [O] Compression type.
01393  *
01394  * RETURNS
01395  *  Success: TRUE
01396  *  Failure: FALSE
01397  */
01398 BOOL WINAPI SetupGetFileCompressionInfoExW( PCWSTR source, PWSTR name, DWORD len, PDWORD required,
01399                                             PDWORD source_size, PDWORD target_size, PUINT type )
01400 {
01401     UINT comp;
01402     BOOL ret = FALSE;
01403     DWORD source_len;
01404 
01405     TRACE("%s, %p, %d, %p, %p, %p, %p\n", debugstr_w(source), name, len, required,
01406           source_size, target_size, type);
01407 
01408     if (!source) return FALSE;
01409 
01410     source_len = lstrlenW( source ) + 1;
01411     if (required) *required = source_len;
01412     if (name && len >= source_len)
01413     {
01414         lstrcpyW( name, source );
01415         ret = TRUE;
01416     }
01417     else return FALSE;
01418 
01419     comp = detect_compression_type( source );
01420     if (type) *type = comp;
01421 
01422     switch (comp)
01423     {
01424     case FILE_COMPRESSION_MSZIP:
01425     case FILE_COMPRESSION_NTCAB:  ret = get_file_sizes_cab( source, source_size, target_size ); break;
01426     case FILE_COMPRESSION_NONE:   ret = get_file_sizes_none( source, source_size, target_size ); break;
01427     case FILE_COMPRESSION_WINLZA: ret = get_file_sizes_lz( source, source_size, target_size ); break;
01428     default: break;
01429     }
01430     return ret;
01431 }
01432 
01433 /***********************************************************************
01434  *      SetupGetFileCompressionInfoA  (SETUPAPI.@)
01435  *
01436  * See SetupGetFileCompressionInfoW.
01437  */
01438 DWORD WINAPI SetupGetFileCompressionInfoA( PCSTR source, PSTR *name, PDWORD source_size,
01439                                            PDWORD target_size, PUINT type )
01440 {
01441     BOOL ret;
01442     DWORD error, required;
01443     LPSTR actual_name;
01444 
01445     TRACE("%s, %p, %p, %p, %p\n", debugstr_a(source), name, source_size, target_size, type);
01446 
01447     if (!source || !name || !source_size || !target_size || !type)
01448         return ERROR_INVALID_PARAMETER;
01449 
01450     ret = SetupGetFileCompressionInfoExA( source, NULL, 0, &required, NULL, NULL, NULL );
01451     if (!(actual_name = MyMalloc( required ))) return ERROR_NOT_ENOUGH_MEMORY;
01452 
01453     ret = SetupGetFileCompressionInfoExA( source, actual_name, required, &required,
01454                                           source_size, target_size, type );
01455     if (!ret)
01456     {
01457         error = GetLastError();
01458         MyFree( actual_name );
01459         return error;
01460     }
01461     *name = actual_name;
01462     return ERROR_SUCCESS;
01463 }
01464 
01465 /***********************************************************************
01466  *      SetupGetFileCompressionInfoW  (SETUPAPI.@)
01467  *
01468  * Get compression type and compressed/uncompressed sizes of a given file.
01469  *
01470  * PARAMS
01471  *  source      [I] File to examine.
01472  *  name        [O] Actual filename used.
01473  *  source_size [O] Size of compressed file.
01474  *  target_size [O] Size of uncompressed file.
01475  *  type        [O] Compression type.
01476  *
01477  * RETURNS
01478  *  Success: ERROR_SUCCESS
01479  *  Failure: Win32 error code.
01480  */
01481 DWORD WINAPI SetupGetFileCompressionInfoW( PCWSTR source, PWSTR *name, PDWORD source_size,
01482                                            PDWORD target_size, PUINT type )
01483 {
01484     BOOL ret;
01485     DWORD error, required;
01486     LPWSTR actual_name;
01487 
01488     TRACE("%s, %p, %p, %p, %p\n", debugstr_w(source), name, source_size, target_size, type);
01489 
01490     if (!source || !name || !source_size || !target_size || !type)
01491         return ERROR_INVALID_PARAMETER;
01492 
01493     ret = SetupGetFileCompressionInfoExW( source, NULL, 0, &required, NULL, NULL, NULL );
01494     if (!(actual_name = MyMalloc( required ))) return ERROR_NOT_ENOUGH_MEMORY;
01495 
01496     ret = SetupGetFileCompressionInfoExW( source, actual_name, required, &required,
01497                                           source_size, target_size, type );
01498     if (!ret)
01499     {
01500         error = GetLastError();
01501         MyFree( actual_name );
01502         return error;
01503     }
01504     *name = actual_name;
01505     return ERROR_SUCCESS;
01506 }
01507 
01508 static DWORD decompress_file_lz( LPCWSTR source, LPCWSTR target )
01509 {
01510     DWORD ret;
01511     LONG error;
01512     INT src, dst;
01513     OFSTRUCT sof, dof;
01514 
01515     if ((src = LZOpenFileW( (LPWSTR)source, &sof, OF_READ )) < 0)
01516     {
01517         ERR("cannot open source file for reading\n");
01518         return ERROR_FILE_NOT_FOUND;
01519     }
01520     if ((dst = LZOpenFileW( (LPWSTR)target, &dof, OF_CREATE )) < 0)
01521     {
01522         ERR("cannot open target file for writing\n");
01523         LZClose( src );
01524         return ERROR_FILE_NOT_FOUND;
01525     }
01526     if ((error = LZCopy( src, dst )) >= 0) ret = ERROR_SUCCESS;
01527     else
01528     {
01529         WARN("failed to decompress file %d\n", error);
01530         ret = ERROR_INVALID_DATA;
01531     }
01532 
01533     LZClose( src );
01534     LZClose( dst );
01535     return ret;
01536 }
01537 
01538 static UINT CALLBACK decompress_or_copy_callback( PVOID context, UINT notification, UINT_PTR param1, UINT_PTR param2 )
01539 {
01540     FILE_IN_CABINET_INFO_W *info = (FILE_IN_CABINET_INFO_W *)param1;
01541 
01542     switch (notification)
01543     {
01544     case SPFILENOTIFY_FILEINCABINET:
01545     {
01546         LPCWSTR filename, targetname = context;
01547         WCHAR *p;
01548 
01549         if ((p = strrchrW( targetname, '\\' ))) filename = p + 1;
01550         else filename = targetname;
01551 
01552         if (!lstrcmpiW( filename, info->NameInCabinet ))
01553         {
01554             strcpyW( info->FullTargetName, targetname );
01555             return FILEOP_DOIT;
01556         }
01557         return FILEOP_SKIP;
01558     }
01559     default: return NO_ERROR;
01560     }
01561 }
01562 
01563 static DWORD decompress_file_cab( LPCWSTR source, LPCWSTR target )
01564 {
01565     BOOL ret;
01566 
01567     ret = SetupIterateCabinetW( source, 0, decompress_or_copy_callback, (PVOID)target );
01568 
01569     if (ret) return ERROR_SUCCESS;
01570     else return GetLastError();
01571 }
01572 
01573 /***********************************************************************
01574  *      SetupDecompressOrCopyFileA  (SETUPAPI.@)
01575  *
01576  * See SetupDecompressOrCopyFileW.
01577  */
01578 DWORD WINAPI SetupDecompressOrCopyFileA( PCSTR source, PCSTR target, PUINT type )
01579 {
01580     DWORD ret = FALSE;
01581     WCHAR *sourceW = NULL, *targetW = NULL;
01582 
01583     if (source && !(sourceW = pSetupMultiByteToUnicode( source, CP_ACP ))) return FALSE;
01584     if (target && !(targetW = pSetupMultiByteToUnicode( target, CP_ACP )))
01585     {
01586         MyFree( sourceW );
01587         return ERROR_NOT_ENOUGH_MEMORY;
01588     }
01589 
01590     ret = SetupDecompressOrCopyFileW( sourceW, targetW, type );
01591 
01592     MyFree( sourceW );
01593     MyFree( targetW );
01594 
01595     return ret;
01596 }
01597 
01598 /***********************************************************************
01599  *      SetupDecompressOrCopyFileW  (SETUPAPI.@)
01600  *
01601  * Copy a file and decompress it if needed.
01602  *
01603  * PARAMS
01604  *  source [I] File to copy.
01605  *  target [I] Filename of the copy.
01606  *  type   [I] Compression type.
01607  *
01608  * RETURNS
01609  *  Success: ERROR_SUCCESS
01610  *  Failure: Win32 error code.
01611  */
01612 DWORD WINAPI SetupDecompressOrCopyFileW( PCWSTR source, PCWSTR target, PUINT type )
01613 {
01614     UINT comp;
01615     DWORD ret = ERROR_INVALID_PARAMETER;
01616 
01617     if (!source || !target) return ERROR_INVALID_PARAMETER;
01618 
01619     if (!type) comp = detect_compression_type( source );
01620     else comp = *type;
01621 
01622     switch (comp)
01623     {
01624     case FILE_COMPRESSION_NONE:
01625         if (CopyFileW( source, target, FALSE )) ret = ERROR_SUCCESS;
01626         else ret = GetLastError();
01627         break;
01628     case FILE_COMPRESSION_WINLZA:
01629         ret = decompress_file_lz( source, target );
01630         break;
01631     case FILE_COMPRESSION_NTCAB:
01632     case FILE_COMPRESSION_MSZIP:
01633         ret = decompress_file_cab( source, target );
01634         break;
01635     default:
01636         WARN("unknown compression type %d\n", comp);
01637         break;
01638     }
01639 
01640     TRACE("%s -> %s %d\n", debugstr_w(source), debugstr_w(target), comp);
01641     return ret;
01642 }
01643 
01644 /*
01645  * implemented (used by pSetupGuidFromString)
01646  */
01647 static BOOL TrimGuidString(PCWSTR szString, LPWSTR szNewString)
01648 {
01649     WCHAR szBuffer[39];
01650     INT Index;
01651 
01652     if (wcslen(szString) == 38)
01653     {
01654         if ((szString[0] == L'{') && (szString[37] == L'}'))
01655         {
01656             for (Index = 0; Index < wcslen(szString); Index++)
01657                 szBuffer[Index] = szString[Index + 1];
01658 
01659             szBuffer[36] = L'\0';
01660             wcscpy(szNewString, szBuffer);
01661             return TRUE;
01662         }
01663     }
01664     szNewString[0] = L'\0';
01665     return FALSE;
01666 }
01667 
01668 /*
01669  * implemented
01670  */
01671 DWORD
01672 WINAPI
01673 pSetupGuidFromString(PCWSTR pString, LPGUID lpGUID)
01674 {
01675     RPC_STATUS Status;
01676     WCHAR szBuffer[39];
01677 
01678     if (!TrimGuidString(pString, szBuffer))
01679     {
01680         return RPC_S_INVALID_STRING_UUID;
01681     }
01682 
01683     Status = UuidFromStringW(szBuffer, lpGUID);
01684     if (Status != RPC_S_OK)
01685     {
01686         return RPC_S_INVALID_STRING_UUID;
01687     }
01688 
01689     return NO_ERROR;
01690 }
01691 
01692 /*
01693  * implemented
01694  */
01695 DWORD
01696 WINAPI
01697 pSetupStringFromGuid(LPGUID lpGUID, PWSTR pString, DWORD dwStringLen)
01698 {
01699     RPC_STATUS Status;
01700     RPC_WSTR rpcBuffer;
01701     WCHAR szBuffer[39];
01702 
01703     if (dwStringLen < 39)
01704     {
01705         return ERROR_INSUFFICIENT_BUFFER;
01706     }
01707 
01708     Status = UuidToStringW(lpGUID, &rpcBuffer);
01709     if (Status != RPC_S_OK)
01710     {
01711         return Status;
01712     }
01713 
01714     wcscpy(szBuffer, L"{");
01715     wcscat(szBuffer, rpcBuffer);
01716     wcscat(szBuffer, L"}");
01717 
01718     wcscpy(pString, szBuffer);
01719 
01720     RpcStringFreeW(&rpcBuffer);
01721     return NO_ERROR;
01722 }
01723 
01724 /*
01725  * implemented
01726  */
01727 BOOL
01728 WINAPI
01729 pSetupIsGuidNull(LPGUID lpGUID)
01730 {
01731     return IsEqualGUID(lpGUID, &GUID_NULL);
01732 }
01733 
01734 /*
01735  * implemented
01736  */
01737 BOOL
01738 WINAPI
01739 pSetupIsUserAdmin(VOID)
01740 {
01741     SID_IDENTIFIER_AUTHORITY Authority = {SECURITY_NT_AUTHORITY};
01742     BOOL bResult = FALSE;
01743     PSID lpSid;
01744 
01745     if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID,
01746                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
01747                                   &lpSid))
01748     {
01749         return FALSE;
01750     }
01751 
01752     if (!CheckTokenMembership(NULL, lpSid, &bResult))
01753     {
01754         bResult = FALSE;
01755     }
01756 
01757     FreeSid(lpSid);
01758 
01759     return bResult;
01760 }
01761 
01762 /***********************************************************************
01763  *      SetupInitializeFileLogW(SETUPAPI.@)
01764  */
01765 HSPFILELOG WINAPI SetupInitializeFileLogW(LPCWSTR LogFileName, DWORD Flags)
01766 {
01767     struct FileLog * Log;
01768     HANDLE hLog;
01769     WCHAR Windir[MAX_PATH];
01770     DWORD ret;
01771 
01772     TRACE("%s, 0x%x\n",debugstr_w(LogFileName),Flags);
01773 
01774     if (Flags & SPFILELOG_SYSTEMLOG)
01775     {
01776         if (!pSetupIsUserAdmin() && !(Flags & SPFILELOG_QUERYONLY))
01777         {
01778             /* insufficient privileges */
01779             SetLastError(ERROR_ACCESS_DENIED);
01780             return INVALID_HANDLE_VALUE;
01781         }
01782 
01783         if (LogFileName || (Flags & SPFILELOG_FORCENEW))
01784         {
01785             /* invalid parameter */
01786             SetLastError(ERROR_INVALID_PARAMETER);
01787             return INVALID_HANDLE_VALUE;
01788         }
01789 
01790         ret = GetSystemWindowsDirectoryW(Windir, MAX_PATH);
01791         if (!ret || ret >= MAX_PATH)
01792         {
01793             /* generic failure */
01794             return INVALID_HANDLE_VALUE;
01795         }
01796 
01797         /* append path */
01798         wcscat(Windir, L"repair\\setup.log");
01799     }
01800     else
01801     {
01802         if (!LogFileName)
01803         {
01804             /* invalid parameter */
01805             SetLastError(ERROR_INVALID_PARAMETER);
01806             return INVALID_HANDLE_VALUE;
01807         }
01808         /* copy filename */
01809         wcsncpy(Windir, LogFileName, MAX_PATH);
01810     }
01811 
01812     if (FileExists(Windir, NULL))
01813     {
01814         /* take ownership */
01815         ret = TakeOwnershipOfFile(Windir);
01816 
01817         if (ret != ERROR_SUCCESS)
01818         {
01819             /* failed */
01820             SetLastError(ret);
01821             return INVALID_HANDLE_VALUE;
01822         }
01823 
01824         if (!SetFileAttributesW(Windir, FILE_ATTRIBUTE_NORMAL))
01825         {
01826             /* failed */
01827             return INVALID_HANDLE_VALUE;
01828         }
01829 
01830         if ((Flags & SPFILELOG_FORCENEW))
01831         {
01832             if (!DeleteFileW(Windir))
01833             {
01834                 /* failed */
01835                 return INVALID_HANDLE_VALUE;
01836             }
01837         }
01838     }
01839 
01840     /* open log file */
01841     hLog = CreateFileW(Windir,
01842                        (Flags & SPFILELOG_QUERYONLY) ? GENERIC_READ : GENERIC_WRITE,
01843                        FILE_SHARE_READ | FILE_SHARE_WRITE,
01844                        NULL,
01845                        OPEN_ALWAYS,
01846                        FILE_ATTRIBUTE_NORMAL,
01847                        NULL);
01848 
01849     if (hLog == INVALID_HANDLE_VALUE)
01850     {
01851         /* failed */
01852         return INVALID_HANDLE_VALUE;
01853     }
01854 
01855     /* close log handle */
01856     CloseHandle(hLog);
01857 
01858     /* allocate file log struct */
01859     Log = HeapAlloc(GetProcessHeap(), 0, sizeof(struct FileLog));
01860     if (!Log)
01861     {
01862         /* not enough memory */
01863         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01864         return INVALID_HANDLE_VALUE;
01865     }
01866 
01867     /* initialize log */
01868     Log->LogName = HeapAlloc(GetProcessHeap(), 0, (wcslen(Windir)+1) * sizeof(WCHAR));
01869     if (!Log->LogName)
01870     {
01871         /* not enough memory */
01872         HeapFree(GetProcessHeap(), 0, Log);
01873         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01874         return INVALID_HANDLE_VALUE;
01875     }
01876 
01877     wcscpy(Log->LogName, Windir);
01878     Log->ReadOnly = (Flags & SPFILELOG_QUERYONLY);
01879     Log->SystemLog = (Flags & SPFILELOG_SYSTEMLOG);
01880 
01881     return (HSPFILELOG)Log;
01882 }
01883 
01884 /***********************************************************************
01885  *      SetupInitializeFileLogA(SETUPAPI.@)
01886  */
01887 HSPFILELOG WINAPI SetupInitializeFileLogA(LPCSTR LogFileName, DWORD Flags)
01888 {
01889     HSPFILELOG hLog;
01890     LPWSTR LogFileNameW = NULL;
01891 
01892     TRACE("%s, 0x%x\n",debugstr_a(LogFileName),Flags);
01893 
01894     if (LogFileName)
01895     {
01896         LogFileNameW = strdupAtoW(LogFileName);
01897 
01898         if (!LogFileNameW)
01899         {
01900             /* not enough memory */
01901             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01902             return INVALID_HANDLE_VALUE;
01903         }
01904 
01905         hLog = SetupInitializeFileLogW(LogFileNameW, Flags);
01906         HeapFree(GetProcessHeap(), 0, LogFileNameW);
01907     }
01908     else
01909     {
01910         hLog = SetupInitializeFileLogW(NULL, Flags);
01911     }
01912 
01913     return hLog;
01914 }
01915 
01916 /***********************************************************************
01917  *      SetupTerminateFileLog(SETUPAPI.@)
01918  */
01919 BOOL WINAPI SetupTerminateFileLog(HANDLE FileLogHandle)
01920 {
01921     struct FileLog * Log;
01922 
01923     TRACE ("%p\n",FileLogHandle);
01924 
01925     Log = (struct FileLog *)FileLogHandle;
01926 
01927     /* free file log handle */
01928     HeapFree(GetProcessHeap(), 0, Log->LogName);
01929     HeapFree(GetProcessHeap(), 0, Log);
01930 
01931     SetLastError(ERROR_SUCCESS);
01932 
01933     return TRUE;
01934 }

Generated on Sat May 26 2012 04:15:47 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.