apithk.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 22k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //
  2. //  APITHK.C
  3. //
  4. //  This file has API thunks that allow shell32 to load and run on
  5. //  multiple versions of NT or Win95.  Since this component needs
  6. //  to load on the base-level NT 4.0 and Win95, any calls to system
  7. //  APIs introduced in later OS versions must be done via GetProcAddress.
  8. // 
  9. //  Also, any code that may need to access data structures that are
  10. //  post-4.0 specific can be added here.
  11. //
  12. //  NOTE:  this file does *not* use the standard precompiled header,
  13. //         so it can set _WIN32_WINNT to a later version.
  14. //
  15. #include "shellprv.h"       // Don't use precompiled header here
  16. #include "msi.h"
  17. #include <appmgmt.h>
  18. #include <userenv.h>
  19. /*----------------------------------------------------------
  20. Purpose: Attempt to get the module handle first (in case the
  21.          DLL is already loaded).  If that doesn't work,
  22.          use LoadLibrary.  
  23.          Warning!!  Be careful how you use this function.
  24.          Theoretically, the 1st thread could use LoadLibrary,
  25.          the 2nd thread could use GetModuleHandle, then
  26.          the 1st thread would FreeLibrary, and suddenly 
  27.          the 2nd thread would have an invalid handle.
  28.          The saving grace is -- for these functions -- the
  29.          DLL is never freed.  But if there's a chance the
  30.          DLL can be freed, don't use this function, just
  31.          use LoadLibrary.
  32.         
  33. */
  34. HINSTANCE _QuickLoadLibrary(LPCTSTR pszModule)
  35. {
  36.     HINSTANCE hinst = GetModuleHandle(pszModule);  // this is fast
  37.     // Since we don't actually bump up the loader count, the module
  38.     // had better be one of the following that is not going to be
  39.     // unloaded except at process termination.
  40.     ASSERT(hinst && 
  41.            (!lstrcmpi(pszModule, TEXT("KERNEL32.DLL"))  || 
  42.             !lstrcmpi(pszModule, TEXT("USER32.DLL"))    ||
  43.             !lstrcmpi(pszModule, TEXT("GDI32.DLL"))     ||
  44.             !lstrcmpi(pszModule, TEXT("ADVAPI32.DLL"))));
  45.     if (NULL == hinst)
  46.         hinst = LoadLibrary(pszModule);
  47.     return hinst;
  48. }
  49. #define PFN_FIRSTTIME   ((void *) -1)
  50. // GetVolumeNameForVolumeMountPoint
  51. typedef BOOL (__stdcall * PFNGETVOLUMENAMEFORVOLUMEMOUNTPOINTW)(
  52.         LPCWSTR lpszFileName,
  53.         LPWSTR lpszVolumePathName,
  54.         DWORD cchBufferLength);
  55. /*----------------------------------------------------------
  56. Purpose: Thunk for NT 5's GetVolumeNameForVolumeMountPointW
  57. */
  58. BOOL NT5_GetVolumeNameForVolumeMountPointW(LPCWSTR lpszFileName,
  59.                 LPWSTR lpszVolumePathName, DWORD cchBufferLength)
  60. {
  61.     static PFNGETVOLUMENAMEFORVOLUMEMOUNTPOINTW s_pfn = PFN_FIRSTTIME;
  62.     if (PFN_FIRSTTIME == s_pfn)
  63.     {
  64.         HINSTANCE hinst = _QuickLoadLibrary(TEXT("KERNEL32.DLL"));
  65.         if (hinst)
  66.             s_pfn = (PFNGETVOLUMENAMEFORVOLUMEMOUNTPOINTW)GetProcAddress(hinst, "GetVolumeNameForVolumeMountPointW");
  67.         else
  68.             s_pfn = NULL;
  69.     }
  70.     if (s_pfn)
  71.         return s_pfn(lpszFileName,lpszVolumePathName,cchBufferLength);
  72.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  73.     return FALSE;    
  74. }
  75. // GetVolumePathName
  76. typedef BOOL (__stdcall * PFNGETVOLUMEPATHNAMEW)(
  77.         LPCWSTR lpszFileName,
  78.         LPWSTR lpszVolumePathName,
  79.         DWORD cchBufferLength);
  80. /*----------------------------------------------------------
  81. Purpose: Thunk for NT 5's GetVolumeNameForVolumeMountPointW
  82. */
  83. BOOL NT5_GetVolumePathNameW(LPCWSTR lpszFileName, LPWSTR lpszVolumePathName,
  84.                 DWORD cchBufferLength)
  85. {
  86.     static PFNGETVOLUMEPATHNAMEW s_pfn = PFN_FIRSTTIME;
  87.     if (PFN_FIRSTTIME == s_pfn)
  88.     {
  89.         HINSTANCE hinst = _QuickLoadLibrary(TEXT("KERNEL32.DLL"));
  90.         if (hinst)
  91.             s_pfn = (PFNGETVOLUMEPATHNAMEW)GetProcAddress(hinst, "GetVolumePathNameW");
  92.         else
  93.             s_pfn = NULL;
  94.     }
  95.     if (s_pfn)
  96.         return s_pfn(lpszFileName,lpszVolumePathName,cchBufferLength);
  97.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  98.     return FALSE;    
  99. }
  100. // EncryptFileW
  101. typedef BOOL (__stdcall * PFNENCRYPTFILEW)(LPCWSTR lpFileName);
  102. /*----------------------------------------------------------
  103. Purpose: Thunk for NT 5's EncryptFileW
  104. */
  105. BOOL NT5_EncryptFileW(LPCWSTR lpFileName)
  106. {
  107.     static PFNENCRYPTFILEW s_pfn = PFN_FIRSTTIME;
  108.     if (PFN_FIRSTTIME == s_pfn)
  109.     {
  110.         HINSTANCE hinst = _QuickLoadLibrary(TEXT("ADVAPI32.DLL"));
  111.         if (hinst)
  112.             s_pfn = (PFNENCRYPTFILEW)GetProcAddress(hinst, "EncryptFileW");
  113.         else
  114.             s_pfn = NULL;
  115.     }
  116.     if (s_pfn)
  117.         return s_pfn(lpFileName);
  118.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  119.     return FALSE;    
  120. }
  121. // DecryptFileW
  122. typedef BOOL (__stdcall * PFNDECRYPTFILEW)(LPCWSTR lpFileName, DWORD dwReserved);
  123. /*----------------------------------------------------------
  124. Purpose: Thunk for NT 5's DecryptFileW
  125. */
  126. BOOL NT5_DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
  127. {
  128.     static PFNDECRYPTFILEW s_pfn = PFN_FIRSTTIME;
  129.     if (PFN_FIRSTTIME == s_pfn)
  130.     {
  131.         HINSTANCE hinst = _QuickLoadLibrary(TEXT("ADVAPI32.DLL"));
  132.         if (hinst)
  133.             s_pfn = (PFNDECRYPTFILEW)GetProcAddress(hinst, "DecryptFileW");
  134.         else
  135.             s_pfn = NULL;
  136.     }
  137.     if (s_pfn)
  138.         return s_pfn(lpFileName, dwReserved);
  139.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  140.     return FALSE;    
  141. }
  142. // InstallApplication
  143. typedef DWORD (__stdcall * PFNINSTALLAPPLICATION)(PINSTALLDATA pInstallInfo);
  144. /*----------------------------------------------------------
  145. Purpose: Thunk for NT 5's InstallApplication
  146. */
  147. DWORD NT5_InstallApplication(PINSTALLDATA pInstallInfo)
  148. {
  149.     static PFNINSTALLAPPLICATION s_pfn = PFN_FIRSTTIME;
  150.     if (PFN_FIRSTTIME == s_pfn)
  151.     {
  152.         HINSTANCE hinst = LoadLibrary(TEXT("ADVAPI32.DLL"));
  153.         if (hinst)
  154.             s_pfn = (PFNINSTALLAPPLICATION)GetProcAddress(hinst, "InstallApplication");
  155.         else
  156.             s_pfn = NULL;
  157.     }
  158.     if (s_pfn)
  159.         return s_pfn(pInstallInfo);
  160.     return ERROR_CALL_NOT_IMPLEMENTED;    
  161. }
  162. typedef INSTALLSTATE (__stdcall *PFNMSIQUERYFEATURESTATEFROMDESCRITORW)(LPCWSTR);
  163. BOOL IsDarwinAdW(LPCWSTR pszDescriptor)
  164. {
  165.     static PFNMSIQUERYFEATURESTATEFROMDESCRITORW s_pfn = PFN_FIRSTTIME;
  166.     if (PFN_FIRSTTIME == s_pfn)
  167.     {
  168.         HINSTANCE hinst = LoadLibrary(TEXT("MSI.DLL"));
  169.         if (hinst)
  170.             s_pfn = (PFNMSIQUERYFEATURESTATEFROMDESCRITORW)
  171.                 GetProcAddress(hinst, "MsiQueryFeatureStateFromDescriptorW");
  172.         else
  173.             s_pfn = NULL;
  174.     }
  175.     if (s_pfn)
  176.         return s_pfn(pszDescriptor) == INSTALLSTATE_ADVERTISED;
  177.     return FALSE;    
  178. }
  179. //---- 
  180. int GetCOLOR_HOTLIGHT()
  181. {
  182.     return (g_bRunOnNT5 || g_bRunOnMemphis) ? COLOR_HOTLIGHT : COLOR_HIGHLIGHT;
  183. }
  184. // these two functions are duplicated from browseui
  185. HINSTANCE GetComctl32Hinst()
  186. {
  187.     static HINSTANCE s_hinst = NULL;
  188.     if (!s_hinst)
  189.         s_hinst = GetModuleHandle(TEXT("comctl32.dll"));
  190.     return s_hinst;
  191. }
  192. STDAPI_(HCURSOR) LoadHandCursor(DWORD dwRes)
  193. {
  194.     if(g_bRunOnNT5 || g_bRunOnMemphis)
  195.     {
  196.         HCURSOR hcur = LoadCursor(NULL, IDC_HAND);  // from USER, system supplied
  197.         if (hcur)
  198.             return hcur;
  199.     }
  200.     return LoadCursor(GetComctl32Hinst(), IDC_HAND_INTERNAL);
  201. }
  202. // GlobalMemoryStatusEx
  203. BOOL NT5_EmulateGlobalMemoryStatusEx(LPMEMORYSTATUSEX pmsex)
  204. {
  205.     if (pmsex->dwLength == sizeof(MEMORYSTATUSEX))
  206.     {
  207.         MEMORYSTATUS ms;
  208.         GlobalMemoryStatus(&ms);
  209.         pmsex->dwMemoryLoad            = ms.dwMemoryLoad;
  210.         pmsex->ullTotalPhys            = ms.dwTotalPhys;
  211.         pmsex->ullAvailPhys            = ms.dwAvailPhys;
  212.         pmsex->ullTotalPageFile        = ms.dwTotalPageFile;
  213.         pmsex->ullAvailPageFile        = ms.dwAvailPageFile;
  214.         pmsex->ullTotalVirtual         = ms.dwTotalVirtual;
  215.         pmsex->ullAvailVirtual         = ms.dwAvailVirtual;
  216.         pmsex->ullAvailExtendedVirtual = 0;
  217.         return TRUE;
  218.     } else {
  219.         return FALSE;
  220.     }
  221. }
  222. typedef BOOL (__stdcall * PFNGLOBALMEMORYSTATUSEX)(LPMEMORYSTATUSEX pmsex);
  223. /*----------------------------------------------------------
  224. Purpose: Thunk for NT 5's GlobalMemoryStatusEx, with fallback on Win9x/NT4
  225. */
  226. BOOL NT5_GlobalMemoryStatusEx(LPMEMORYSTATUSEX pmsex)
  227. {
  228.     static PFNGLOBALMEMORYSTATUSEX s_pfn;
  229.     if (s_pfn == NULL)
  230.     {
  231.         HINSTANCE hinst = _QuickLoadLibrary(TEXT("KERNEL32.DLL"));
  232.         if (hinst)
  233.             s_pfn = (PFNGLOBALMEMORYSTATUSEX)GetProcAddress(hinst, "GlobalMemoryStatusEx");
  234.         if (s_pfn == NULL)
  235.             s_pfn = NT5_EmulateGlobalMemoryStatusEx;
  236.     }
  237.     return s_pfn(pmsex);
  238. }
  239. BOOL IsColorKey(RGBQUAD rgbPixel, COLORREF crKey)
  240. {
  241.     // COLORREF is backwards to RGBQUAD
  242.     return InRange( rgbPixel.rgbBlue,  ((crKey & 0xFF0000) >> 16) - 5, ((crKey & 0xFF0000) >> 16) + 5) &&
  243.            InRange( rgbPixel.rgbGreen, ((crKey & 0x00FF00) >>  8) - 5, ((crKey & 0x00FF00) >>  8) + 5) &&
  244.            InRange( rgbPixel.rgbRed,   ((crKey & 0x0000FF) >>  0) - 5, ((crKey & 0x0000FF) >>  0) + 5);
  245. }
  246. /*----------------------------------------------------------*/
  247. typedef BOOL (* PFNUPDATELAYEREDWINDOW)
  248.     (HWND hwnd, 
  249.     HDC hdcDest,
  250.     POINT *pptDst,
  251.     SIZE *psize,
  252.     HDC hdcSrc,
  253.     POINT *pptSrc,
  254.     COLORREF crKey,
  255.     BLENDFUNCTION *pblend,
  256.     DWORD dwFlags);
  257. BOOL NT5_UpdateLayeredWindow(HWND hwnd, HDC hdcDest, POINT* pptDest, SIZE* psize, 
  258.                         HDC hdcSrc, POINT* pptSrc, COLORREF crKey, BLENDFUNCTION* pblend, DWORD dwFlags)
  259. {
  260.     BOOL bRet = FALSE;
  261. #if(_WIN32_WINNT >= 0x0500)
  262.     static PFNUPDATELAYEREDWINDOW pfn = NULL;
  263.     if (NULL == pfn)
  264.     {
  265.         HMODULE hmod = GetModuleHandle(TEXT("USER32"));
  266.         
  267.         if (hmod)
  268.             pfn = (PFNUPDATELAYEREDWINDOW)GetProcAddress(hmod, "UpdateLayeredWindow");
  269.     }
  270.     if (pfn)
  271.     {
  272.         // The user implementation is lame and does not implement this functionality
  273.         BITMAPINFO      bmi;
  274.         HDC             hdcRGBA;
  275.         HBITMAP         hbmRGBA;
  276.         VOID*           pBits;
  277.         LONG            i;
  278.         BLENDFUNCTION   blend;
  279.         ULONG*          pul;
  280.         POINT           ptSrc;
  281.         BOOL            bRet;
  282.  
  283.         hdcRGBA = NULL;
  284.  
  285.         if ((dwFlags & (ULW_ALPHA | ULW_COLORKEY)) == (ULW_ALPHA | ULW_COLORKEY))
  286.         {
  287.             if (hdcSrc)
  288.             {
  289.                 RtlZeroMemory(&bmi, sizeof(bmi));
  290.         
  291.                 bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
  292.                 bmi.bmiHeader.biWidth       = psize->cx;
  293.                 bmi.bmiHeader.biHeight      = psize->cy;
  294.                 bmi.bmiHeader.biPlanes      = 1;
  295.                 bmi.bmiHeader.biBitCount    = 32;
  296.                 bmi.bmiHeader.biCompression = BI_RGB;
  297.         
  298.                 hbmRGBA = CreateDIBSection(hdcDest,
  299.                                            &bmi,
  300.                                            DIB_RGB_COLORS,
  301.                                            &pBits,
  302.                                            NULL,
  303.                                            0);
  304.     
  305.                 hdcRGBA = CreateCompatibleDC(hdcDest);
  306.     
  307.                 if (!hbmRGBA || !hdcRGBA)
  308.                 {
  309.                     DeleteObject(hbmRGBA);
  310.                     DeleteObject(hdcRGBA);
  311.                     return(FALSE);
  312.                 }
  313.     
  314.                 SelectObject(hdcRGBA, hbmRGBA);
  315.     
  316.                 BitBlt(hdcRGBA, 0, 0, psize->cx, psize->cy,
  317.                        hdcSrc, pptSrc->x, pptSrc->y, SRCCOPY);
  318.     
  319.                 pul = pBits;
  320.     
  321.                 for (i = psize->cx * psize->cy; i != 0; i--)
  322.                 {
  323.                     if (IsColorKey(*(RGBQUAD*)pul, crKey))
  324.                     {
  325.                         // Write a pre-multiplied value of 0:
  326.  
  327.                         *pul = 0;
  328.                     }
  329.                     else
  330.                     {
  331.                         // Where the bitmap is not the transparent color, change the
  332.                         // alpha value to opaque:
  333.     
  334.                         ((RGBQUAD*) pul)->rgbReserved = 0xff;
  335.                     }
  336.     
  337.                     pul++;
  338.                 }
  339.  
  340.                 // Change the parameters to account for the fact that we're now
  341.                 // providing only a 32-bit per-pixel alpha source:
  342.  
  343.                 ptSrc.x = 0;
  344.                 ptSrc.y = 0;
  345.                 pptSrc = &ptSrc;
  346.                 hdcSrc = hdcRGBA;
  347.             }
  348.  
  349.             blend = *pblend;
  350.             blend.AlphaFormat = AC_SRC_ALPHA;   
  351.  
  352.             pblend = &blend;
  353.             dwFlags = ULW_ALPHA;
  354.         }
  355.         bRet = pfn(hwnd, hdcDest, pptDest, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
  356.         if (hdcRGBA)
  357.         {
  358.             DeleteObject(hdcRGBA);
  359.             DeleteObject(hbmRGBA);
  360.         }
  361.     }
  362. #endif
  363.     return bRet;    
  364. }
  365. BOOL IsRemoteSession()
  366. {
  367.     return GetSystemMetrics(SM_REMOTESESSION);
  368. }
  369. // GetLongPathName
  370. BOOL NT5_EmulateGetLongPathName(LPCTSTR pszShort, LPTSTR pszLong, DWORD cchBuf)
  371. {
  372.     //  To convert a short name to a long name, convert it to a pidl
  373.     //  and then convert the pidl to a long name.  This is bad because
  374.     //  if the file lives inside a junction point, we end up loading
  375.     //  the junction handler even though we don't use it for anything!
  376.     LPITEMIDLIST pidl;
  377.     BOOL fRc = FALSE;
  378.     ASSERT(cchBuf >= MAX_PATH);
  379.     pidl = ILCreateFromPath(pszShort);
  380.     if (pidl)
  381.     {
  382.         fRc = SHGetPathFromIDList(pidl, pszLong);
  383.         ILFree(pidl);
  384.     }
  385.     return fRc;
  386. }
  387. typedef BOOL (__stdcall * PFNGETLONGPATHNAME)(LPCTSTR pszShort, LPTSTR pszLong, DWORD cchBuf);
  388. /*----------------------------------------------------------
  389. Purpose: Thunk for NT4/Win98's GetLongPathName, with fallback on Win95
  390. */
  391. BOOL NT5_GetLongPathName(LPCTSTR pszShort, LPTSTR pszLong, DWORD cchBuf)
  392. {
  393.     static PFNGETLONGPATHNAME s_pfn;
  394.     if (s_pfn == NULL)
  395.     {
  396.         HINSTANCE hinst = _QuickLoadLibrary(TEXT("KERNEL32.DLL"));
  397.         if (hinst)
  398. #ifdef UNICODE
  399.             s_pfn = (PFNGETLONGPATHNAME)GetProcAddress(hinst, "GetLongPathNameW");
  400. #else
  401.             s_pfn = (PFNGETLONGPATHNAME)GetProcAddress(hinst, "GetLongPathNameA");
  402. #endif
  403.         if (s_pfn == NULL)
  404.             s_pfn = NT5_EmulateGetLongPathName;
  405.     }
  406.     return s_pfn(pszShort, pszLong, cchBuf);
  407. }
  408. typedef HDEVNOTIFY (__stdcall * PFNREGISTERDEVICENOTIFICATION)(
  409.     IN HANDLE hRecipient,
  410.     IN LPVOID NotificationFilter,
  411.     IN DWORD Flags
  412.     );
  413. /*----------------------------------------------------------
  414. Purpose: Thunk for NT5/Win98's RegisterDeviceNotification
  415. */
  416. STDAPI_(HDEVNOTIFY) Win98_RegisterDeviceNotification(
  417.     IN HANDLE hRecipient,
  418.     IN LPVOID NotificationFilter,
  419.     IN DWORD Flags
  420.     )
  421. {
  422.     static PFNREGISTERDEVICENOTIFICATION s_pfn = PFN_FIRSTTIME;
  423.     if (s_pfn == PFN_FIRSTTIME)
  424.     {
  425.         HINSTANCE hinst = _QuickLoadLibrary(TEXT("USER32.DLL"));
  426.         if (hinst)
  427. #ifdef UNICODE
  428.             s_pfn = (PFNREGISTERDEVICENOTIFICATION)GetProcAddress(hinst, "RegisterDeviceNotificationW");
  429. #else
  430.             s_pfn = (PFNREGISTERDEVICENOTIFICATION)GetProcAddress(hinst, "RegisterDeviceNotificationA");
  431. #endif
  432.         else
  433.             s_pfn = NULL;
  434.     }
  435.     if (s_pfn)
  436.     {
  437.         return s_pfn(hRecipient, NotificationFilter, Flags);
  438.     }
  439.     else
  440.     {
  441.         return NULL;
  442.     }
  443. }
  444. typedef BOOL (__stdcall * PFNUNREGISTERDEVICENOTIFICATION)(
  445.     IN HDEVNOTIFY Handle
  446.     );
  447. /*----------------------------------------------------------
  448. Purpose: Thunk for NT5/Win98's UnregisterDeviceNotification
  449. */
  450. STDAPI_(BOOL) Win98_UnregisterDeviceNotification(
  451.     IN HDEVNOTIFY Handle
  452.     )
  453. {
  454.     static PFNUNREGISTERDEVICENOTIFICATION s_pfn = PFN_FIRSTTIME;
  455.     if (s_pfn == PFN_FIRSTTIME)
  456.     {
  457.         HINSTANCE hinst = _QuickLoadLibrary(TEXT("USER32.DLL"));
  458.         if (hinst)
  459.             s_pfn = (PFNUNREGISTERDEVICENOTIFICATION)GetProcAddress(hinst, "UnregisterDeviceNotification");
  460.         else
  461.             s_pfn = NULL;
  462.     }
  463.     if (s_pfn)
  464.     {
  465.         return s_pfn(Handle);
  466.     }
  467.     else
  468.     {
  469.         return FALSE;
  470.     }
  471. }
  472. #ifdef WINNT
  473. typedef UINT (__stdcall * PFNGETSYSTEMWINDOWSDIRECTORYW)(LPWSTR pwszBuffer, UINT cchBuff);
  474. //
  475. // GetSystemWindowsDirectory is NT5 only. Basically this api exists because on HYDRA systems
  476. // kernel32 lies and returns a directory under %userprofile% to "help app compat on hydra"
  477. //
  478. UINT NT5_GetSystemWindowsDirectoryW(LPWSTR pwszBuffer, UINT cchBuff)
  479. {
  480.     static PFNGETSYSTEMWINDOWSDIRECTORYW s_pfn = PFN_FIRSTTIME;
  481.     if (PFN_FIRSTTIME == s_pfn)
  482.     {
  483.         HINSTANCE hinst = _QuickLoadLibrary(TEXT("KERNEL32.DLL"));
  484.         if (hinst)
  485.             s_pfn = (PFNGETSYSTEMWINDOWSDIRECTORYW)GetProcAddress(hinst, "GetSystemWindowsDirectoryW");
  486.         else
  487.             s_pfn = NULL;
  488.     }
  489.     if (s_pfn)
  490.     {
  491.         // we use the new API so we dont get lied to by hydra
  492.         return s_pfn(pwszBuffer, cchBuff);
  493.     }
  494.     else
  495.     {
  496.         // must be on NT4, fall back to the ol'e GetWindowsDirectory
  497.         return GetWindowsDirectoryW(pwszBuffer, cchBuff);
  498.     }
  499. }
  500. #endif // WINNT
  501. #ifdef WINNT
  502. typedef BOOL (__stdcall * PFNCONVERTSIDTOSTRINGSIDW)(
  503.     IN   PSID               psid,
  504.     OUT  LPTSTR *           StringSid
  505. );
  506. BOOL NT5_ConvertSidToStringSidW(
  507.     IN   PSID               psid,
  508.     OUT  LPTSTR *           StringSid
  509. )
  510. {
  511.     static PFNCONVERTSIDTOSTRINGSIDW s_pfn = PFN_FIRSTTIME;
  512.     if (s_pfn == PFN_FIRSTTIME)
  513.         s_pfn = (PFNCONVERTSIDTOSTRINGSIDW)GetProcAddress(_QuickLoadLibrary(TEXT("ADVAPI32.DLL")), "ConvertSidToStringSidW");
  514.     if (s_pfn)
  515.         return s_pfn(psid, StringSid);
  516.     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  517.     return FALSE;
  518. }
  519. #endif
  520. // GetSystemDefaultUILanguage
  521. typedef LANGID (__stdcall * PFNGETSYSTEMDEFAULTUILANGUAGE)();
  522. /*----------------------------------------------------------
  523. Purpose: Thunk for NT 5's GetSystemDefaultUILanguage
  524. */
  525. LANGID NT5_GetSystemDefaultUILanguage()
  526. {
  527.     static PFNGETSYSTEMDEFAULTUILANGUAGE s_pfn = PFN_FIRSTTIME;
  528.     if (PFN_FIRSTTIME == s_pfn)
  529.     {
  530.         HINSTANCE hinst = LoadLibrary(TEXT("KERNEL32.DLL"));
  531.         if (hinst)
  532.             s_pfn = (PFNGETSYSTEMDEFAULTUILANGUAGE)
  533.                 GetProcAddress(hinst, "GetSystemDefaultUILanguage");
  534.         else
  535.             s_pfn = NULL;
  536.     }
  537.     if (s_pfn)
  538.         return s_pfn();
  539.     return MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT);
  540. }
  541. // MsiGetProductInfo
  542. typedef UINT (WINAPI * PFNMSIGETPRODUCTINFO) (LPCTSTR szProduct, LPCTSTR szAttribute, LPTSTR lpValueBuf, DWORD *pcchValueBuf); 
  543. /*----------------------------------------------------------
  544. Purpose: Thunk for NT 5's MsiGetProductInfo
  545. */
  546. UINT MSI_MsiGetProductInfo(LPCTSTR szProduct, LPCTSTR szAttribute, LPTSTR lpValueBuf, DWORD* pcchValueBuf)
  547. {
  548.     static PFNMSIGETPRODUCTINFO s_pfn = PFN_FIRSTTIME;
  549.     if (PFN_FIRSTTIME == s_pfn)
  550.     {
  551.         HINSTANCE hinst = LoadLibrary(TEXT("MSI.DLL"));
  552.         if (hinst)
  553.         {
  554.             // The unicode-decorated MSI APIs translate to ansi internally
  555.             // on Win95, so it should be safe to call them all the time.
  556. #ifdef UNICODE 
  557.             s_pfn = (PFNMSIGETPRODUCTINFO)GetProcAddress(hinst, "MsiGetProductInfoW");
  558. #else
  559.             s_pfn = (PFNMSIGETPRODUCTINFO)GetProcAddress(hinst, "MsiGetProductInfoA");
  560. #endif
  561.         }
  562.         else
  563.             s_pfn = NULL;
  564.     }
  565.     if (s_pfn)
  566.         return s_pfn(szProduct, szAttribute, lpValueBuf, pcchValueBuf);
  567.     return ERROR_CALL_NOT_IMPLEMENTED;
  568. }
  569. typedef BOOL (__stdcall * PFNTERMSRVAPPINSTALLMODE)(void);
  570. //
  571. // This function is used by hydra (Terminal Server) to see if we
  572. // are in application install mode
  573. //
  574. BOOL NT5_TermsrvAppInstallMode()
  575. {
  576.     static PFNTERMSRVAPPINSTALLMODE s_pfn = PFN_FIRSTTIME;
  577.     if (PFN_FIRSTTIME == s_pfn)
  578.     {
  579.         HINSTANCE hinst = _QuickLoadLibrary(TEXT("KERNEL32.DLL"));
  580.         if (hinst)
  581.         {
  582.             s_pfn = (PFNTERMSRVAPPINSTALLMODE)GetProcAddress(hinst, "TermsrvAppInstallMode");
  583.         }
  584.         else
  585.         {
  586.             s_pfn = NULL;
  587.         }
  588.     }
  589.     if (s_pfn)
  590.     {
  591.         return s_pfn();
  592.     }
  593.     return FALSE;
  594. }
  595. LPTSTR GetEnvBlock(HANDLE hUserToken)
  596. {
  597.     LPTSTR pszRet = NULL;
  598. #ifdef WINNT  
  599.     if (hUserToken && IsOS(OS_NT5))
  600.         CreateEnvironmentBlock(&pszRet, hUserToken, TRUE);
  601.     else
  602. #endif WINNT
  603.         pszRet = (LPTSTR) GetEnvironmentStrings();
  604.     return pszRet;
  605. }
  606. void FreeEnvBlock(HANDLE hUserToken, LPTSTR pszEnv)
  607. {
  608.     if (pszEnv)
  609.     {
  610. #ifdef WINNT  
  611.         if (hUserToken && IsOS(OS_NT5))
  612.             DestroyEnvironmentBlock(pszEnv);
  613.         else
  614. #endif WINNT
  615.             FreeEnvironmentStrings(pszEnv);
  616.     }
  617. }
  618. STDAPI_(BOOL) IsWM_GETOBJECT( UINT uMsg )
  619. {
  620. #if WINVER >= 0x0500 
  621.     return WM_GETOBJECT == uMsg;
  622. #else
  623.     return FALSE;
  624. #endif
  625. }
  626. STDAPI_(BOOL) GetAllUsersDirectory(LPTSTR pszPath)
  627. {
  628. #ifdef WINNT
  629.     DWORD cbData = MAX_PATH;
  630.     return GetAllUsersProfileDirectoryW(pszPath, &cbData);
  631. #else    
  632.     return GetSystemWindowsDirectory(pszPath, MAX_PATH);
  633. #endif
  634. }
  635. #ifdef WINNT
  636. #undef ExpandEnvironmentStringsForUserW
  637. STDAPI_(BOOL) NT5_ExpandEnvironmentStringsForUserW(HANDLE hToken, LPCWSTR pszExpand, LPWSTR pszOut, DWORD cchOut)
  638. {
  639.     if (g_bRunOnNT5)
  640.     {
  641.         return ExpandEnvironmentStringsForUserW(hToken, pszExpand, pszOut, cchOut);
  642.     }
  643.     
  644.     return SHExpandEnvironmentStrings(pszExpand, pszOut, cchOut);
  645. }
  646. #endif // WINNT
  647. #undef GetDefaultUserProfileDirectoryW
  648. STDAPI_(BOOL) NT5_GetDefaultUserProfileDirectoryW(LPWSTR pszPath, LPDWORD pcch)
  649. {
  650.     BOOL bRet;
  651.     
  652.     if (g_bRunOnNT5)
  653.         bRet = GetDefaultUserProfileDirectoryW(pszPath, pcch);
  654.     else
  655.     {
  656.         *pcch = 0;
  657.         *pszPath = 0;
  658.         bRet = FALSE;
  659.     }
  660.     return bRet;
  661. }