apithk.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 28k
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 "priv.h"       // Don't use precompiled header here
  16. #include "appwiz.h"
  17. #define c_szARPJob  TEXT("ARP Job")
  18. // Return: hIOPort for the CompletionPort
  19. HANDLE _SetJobCompletionPort(HANDLE hJob)
  20. {
  21.     HANDLE hRet = NULL;
  22.     HANDLE hIOPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)hJob, 1 );
  23.     if ( hIOPort != NULL )
  24.     {
  25.         JOBOBJECT_ASSOCIATE_COMPLETION_PORT CompletionPort;
  26.         CompletionPort.CompletionKey = hJob ;
  27.         CompletionPort.CompletionPort = hIOPort;
  28.         if (SetInformationJobObject( hJob,JobObjectAssociateCompletionPortInformation,
  29.                                      &CompletionPort, sizeof(CompletionPort) ) )
  30.         {   
  31.             hRet = hIOPort;
  32.         }
  33.     }
  34.     return hRet;
  35. }
  36. STDAPI_(DWORD) WaitingThreadProc(void *pv)
  37. {
  38.     HANDLE hIOPort = (HANDLE)pv;
  39.     // RIP(hIOPort);
  40.     
  41.     DWORD dwCompletionCode;
  42.     PVOID pCompletionKey;
  43.     LPOVERLAPPED lpOverlapped;
  44.     
  45.     while (TRUE)
  46.     {
  47.         // Wait for all the processes to finish...
  48.         if (!GetQueuedCompletionStatus( hIOPort, &dwCompletionCode, (PULONG_PTR) &pCompletionKey,
  49.                                         &lpOverlapped, INFINITE ) || (dwCompletionCode == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO))
  50.         {
  51.             break;
  52.         }
  53.     }
  54.     
  55.     return 0;
  56. }
  57. EXTERN_C void WaitForThreadDeath(HWND hDlg, HANDLE FAR * phThread, DWORD dwMilliseconds);
  58. /*-------------------------------------------------------------------------
  59. Purpose: Creates a process and waits for it to finish
  60. */
  61. STDAPI_(BOOL) NT5_CreateAndWaitForProcess(LPTSTR pszExeName)
  62. {
  63.     PROCESS_INFORMATION pi = {0};
  64.     STARTUPINFO si = {0};
  65.     BOOL fWorked = FALSE;
  66. #ifdef WX86
  67.     DWORD  cchArch;
  68.     WCHAR  szArchValue[32];
  69. #endif    
  70.     HANDLE hJob = CreateJobObject(NULL, c_szARPJob);
  71.     
  72.     if (hJob)
  73.     {
  74.         HANDLE hIOPort = _SetJobCompletionPort(hJob);
  75.         if (hIOPort)
  76.         {
  77.             DWORD dwCreationFlags = 0;
  78.             // Create the install process
  79.             si.cb = sizeof(si);
  80. #ifdef WX86
  81.             if (bWx86Enabled && bForceX86Env) {
  82.                 cchArch = GetEnvironmentVariableW(ProcArchName,
  83.                     szArchValue,
  84.                     sizeof(szArchValue)
  85.                     );
  86.                 if (!cchArch || cchArch >= sizeof(szArchValue)) {
  87.                     szArchValue[0]=L'';
  88.                 }
  89.                 SetEnvironmentVariableW(ProcArchName, L"x86");
  90.             }
  91. #endif
  92.             dwCreationFlags = CREATE_SUSPENDED | CREATE_SEPARATE_WOW_VDM;
  93.             
  94.             // Create the process
  95.             fWorked = CreateProcess(NULL, pszExeName, NULL, NULL, FALSE, dwCreationFlags, NULL, NULL,
  96.                                     &si, &pi);
  97.             if (fWorked)
  98.             {
  99.                 BOOL bAssigned = FALSE;
  100.             
  101.                 if (AssignProcessToJobObject(hJob, pi.hProcess))
  102.                 {                    
  103.                     ResumeThread(pi.hThread);
  104.                     bAssigned = TRUE;
  105.                 }
  106.                 else
  107.                     TerminateProcess( pi.hProcess, ERROR_ACCESS_DENIED);
  108.                 CloseHandle(pi.hProcess);
  109.                 CloseHandle(pi.hThread);
  110. #ifdef WX86
  111.                 if (bWx86Enabled && bForceX86Env) 
  112.                     SetEnvironmentVariableW(ProcArchName, szArchValue);
  113. #endif
  114.                 // Now wait for the processes to finish
  115.                 if (bAssigned)
  116.                 {
  117.                     HANDLE hThread;
  118.                     DWORD idThread;
  119.                     // Create the waiting thread.
  120.                     hThread = CreateThread(NULL, 0, WaitingThreadProc,
  121.                                  (LPVOID)hIOPort, 0, &idThread);
  122.                     if (hThread)
  123.                     {
  124.                         WaitForThreadDeath(NULL, &hThread, INFINITE);
  125.                         CloseHandle(hThread);
  126.                     }
  127.                 }
  128.             }
  129.             CloseHandle(hIOPort);
  130.         }
  131.         CloseHandle(hJob);
  132.     }
  133.     return fWorked;
  134. }
  135. #define PFN_FIRSTTIME   ((void *)0xFFFFFFFF)
  136. // GetLongPathName
  137. typedef UINT (WINAPI * PFNGETLONGPATHNAME)(LPCTSTR pszShortPath, LPTSTR pszLongBuf, DWORD cchBuf); 
  138. /*----------------------------------------------------------
  139. Purpose: Thunk for NT 5's GetLongPathName
  140. */
  141. DWORD NT5_GetLongPathName(LPCTSTR pszShortPath, LPTSTR pszLongBuf, DWORD cchBuf)
  142. {
  143.     static PFNGETLONGPATHNAME s_pfn = PFN_FIRSTTIME;
  144.     if (PFN_FIRSTTIME == s_pfn)
  145.     {
  146.         // It is safe to GetModuleHandle KERNEL32 because we implicitly link
  147.         // to it, so it is guaranteed to be loaded in every thread.
  148.         
  149.         HINSTANCE hinst = GetModuleHandleA("KERNEL32.DLL");
  150.         if (hinst)
  151.         {
  152.             // The unicode-decorated MSI APIs translate to ansi internally
  153.             // on Win95, so it should be safe to call them all the time.
  154. #ifdef UNICODE 
  155.             s_pfn = (PFNGETLONGPATHNAME)GetProcAddress(hinst, "GetLongPathNameW");
  156. #else
  157.             s_pfn = (PFNGETLONGPATHNAME)GetProcAddress(hinst, "GetLongPathNameA");
  158. #endif
  159.         }
  160.         else
  161.             s_pfn = NULL;
  162.     }
  163.     if (s_pfn)
  164.         return s_pfn(pszShortPath, pszLongBuf, cchBuf);
  165.     if (0 < cchBuf && pszLongBuf)
  166.         *pszLongBuf = 0;
  167.         
  168.     return 0;       // failure
  169. }
  170. // VerSetConditionMask
  171. typedef ULONGLONG (WINAPI * PFNVERSETCONDITIONMASK)(ULONGLONG conditionMask, DWORD dwTypeMask, BYTE condition); 
  172. /*----------------------------------------------------------
  173. Purpose: Thunk for NT 5's VerSetConditionMask
  174. */
  175. ULONGLONG NT5_VerSetConditionMask(ULONGLONG conditionMask, DWORD dwTypeMask, BYTE condition)
  176. {
  177.     static PFNVERSETCONDITIONMASK s_pfn = PFN_FIRSTTIME;
  178.     if (PFN_FIRSTTIME == s_pfn)
  179.     {
  180.         // It is safe to GetModuleHandle KERNEL32 because we implicitly link
  181.         // to it, so it is guaranteed to be loaded in every thread.
  182.         
  183.         HINSTANCE hinst = GetModuleHandleA("KERNEL32.DLL");
  184.         if (hinst)
  185.             s_pfn = (PFNVERSETCONDITIONMASK)GetProcAddress(hinst, "VerSetConditionMask");
  186.         else
  187.             s_pfn = NULL;
  188.     }
  189.     if (s_pfn)
  190.         return s_pfn(conditionMask, dwTypeMask, condition);
  191.     return 0;       // failure
  192. }
  193. // MsiReinstallProduct
  194. typedef UINT (WINAPI * PFNMSIREINSTALLPRODUCT) (LPCTSTR szProduct, DWORD dwReinstallMode); 
  195. /*----------------------------------------------------------
  196. Purpose: Thunk for NT 5's MsiReinstallProduct
  197. */
  198. UINT MSI_MsiReinstallProduct(LPCTSTR szProduct, DWORD dwReinstallMode)
  199. {
  200.     static PFNMSIREINSTALLPRODUCT s_pfn = PFN_FIRSTTIME;
  201.     if (PFN_FIRSTTIME == s_pfn)
  202.     {
  203.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  204.         if (hinst)
  205.         {
  206.             // The unicode-decorated MSI APIs translate to ansi internally
  207.             // on Win95, so it should be safe to call them all the time.
  208. #ifdef UNICODE 
  209.             s_pfn = (PFNMSIREINSTALLPRODUCT)GetProcAddress(hinst, "MsiReinstallProductW");
  210. #else
  211.             s_pfn = (PFNMSIREINSTALLPRODUCT)GetProcAddress(hinst, "MsiReinstallProductA");
  212. #endif
  213.         }
  214.         else
  215.             s_pfn = NULL;
  216.     }
  217.     if (s_pfn)
  218.         return s_pfn(szProduct, dwReinstallMode);
  219.     return ERROR_CALL_NOT_IMPLEMENTED;
  220. }
  221. // MsiEnumProducts
  222. typedef UINT (WINAPI * PFNMSIENUMPRODUCTS) (DWORD iProductIndex, LPTSTR lpProductBuf);
  223. /*----------------------------------------------------------
  224. Purpose: Thunk for NT 5's MsiEnumProducts
  225. */
  226. UINT MSI_MsiEnumProducts(DWORD iProductIndex, LPTSTR lpProductBuf)
  227. {
  228.     static PFNMSIENUMPRODUCTS s_pfn = PFN_FIRSTTIME;
  229.     if (PFN_FIRSTTIME == s_pfn)
  230.     {
  231.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  232.         
  233.         if (hinst)
  234.         {
  235.             // The unicode-decorated MSI APIs translate to ansi internally
  236.             // on Win95, so it should be safe to call them all the time.
  237. #ifdef UNICODE 
  238.             s_pfn = (PFNMSIENUMPRODUCTS)GetProcAddress(hinst, "MsiEnumProductsW");
  239. #else
  240.             s_pfn = (PFNMSIENUMPRODUCTS)GetProcAddress(hinst, "MsiEnumProductsA");
  241. #endif
  242.         }
  243.         else
  244.             s_pfn = NULL;
  245.     }
  246.     if (s_pfn)
  247.         return s_pfn(iProductIndex, lpProductBuf);
  248.     return ERROR_CALL_NOT_IMPLEMENTED;
  249. }
  250. // MsiEnumFeatures
  251. typedef UINT (WINAPI * PFNMSIENUMFEATURES) (LPCTSTR  szProduct, DWORD iFeatureIndex, LPTSTR   lpFeatureBuf, LPTSTR   lpParentBuf);
  252. /*----------------------------------------------------------
  253. Purpose: Thunk for NT 5's MsiEnumFeatures
  254. */
  255. UINT MSI_MsiEnumFeatures(LPCTSTR szProduct, DWORD iFeatureIndex, LPTSTR lpFeatureBuf, LPTSTR lpParentBuf)
  256. {
  257.     static PFNMSIENUMFEATURES s_pfn = PFN_FIRSTTIME;
  258.     if (PFN_FIRSTTIME == s_pfn)
  259.     {
  260.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  261.         if (hinst)
  262.         {
  263.             // The unicode-decorated MSI APIs translate to ansi internally
  264.             // on Win95, so it should be safe to call them all the time.
  265. #ifdef UNICODE 
  266.             s_pfn = (PFNMSIENUMFEATURES)GetProcAddress(hinst, "MsiEnumFeaturesW");
  267. #else
  268.             s_pfn = (PFNMSIENUMFEATURES)GetProcAddress(hinst, "MsiEnumFeaturesA");
  269. #endif
  270.         }
  271.         else
  272.             s_pfn = NULL;
  273.     }
  274.     if (s_pfn)
  275.         return s_pfn(szProduct, iFeatureIndex, lpFeatureBuf, lpParentBuf);
  276.     return ERROR_CALL_NOT_IMPLEMENTED;
  277. }
  278. // MsiGetProductInfo
  279. typedef UINT (WINAPI * PFNMSIGETPRODUCTINFO) (LPCTSTR szProduct, LPCTSTR szAttribute, LPTSTR lpValueBuf, DWORD *pcchValueBuf); 
  280. /*----------------------------------------------------------
  281. Purpose: Thunk for NT 5's MsiGetProductInfo
  282. */
  283. UINT MSI_MsiGetProductInfo(LPCTSTR szProduct, LPCTSTR szAttribute, LPTSTR lpValueBuf, DWORD *pcchValueBuf)
  284. {
  285.     static PFNMSIGETPRODUCTINFO s_pfn = PFN_FIRSTTIME;
  286.     if (PFN_FIRSTTIME == s_pfn)
  287.     {
  288.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  289.         if (hinst)
  290.         {
  291.             // The unicode-decorated MSI APIs translate to ansi internally
  292.             // on Win95, so it should be safe to call them all the time.
  293. #ifdef UNICODE 
  294.             s_pfn = (PFNMSIGETPRODUCTINFO)GetProcAddress(hinst, "MsiGetProductInfoW");
  295. #else
  296.             s_pfn = (PFNMSIGETPRODUCTINFO)GetProcAddress(hinst, "MsiGetProductInfoA");
  297. #endif
  298.         }
  299.         else
  300.             s_pfn = NULL;
  301.     }
  302.     if (s_pfn)
  303.         return s_pfn(szProduct, szAttribute, lpValueBuf, pcchValueBuf);
  304.     return ERROR_CALL_NOT_IMPLEMENTED;
  305. }
  306. // MsiSetInternalUI
  307. typedef INSTALLUILEVEL (WINAPI * PFNMSISETINTERNALUI) (INSTALLUILEVEL dwUILevel, HWND * phwnd);
  308. /*----------------------------------------------------------
  309. Purpose: Thunk for NT 5's MsiSetInternalUI
  310. */
  311. INSTALLUILEVEL MSI_MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND * phwnd)
  312. {
  313.     static PFNMSISETINTERNALUI s_pfn = PFN_FIRSTTIME;
  314.     if (PFN_FIRSTTIME == s_pfn)
  315.     {
  316.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  317.         if (hinst)
  318.         {
  319.             s_pfn = (PFNMSISETINTERNALUI)GetProcAddress(hinst, "MsiSetInternalUI");
  320.         }
  321.         else
  322.             s_pfn = NULL;
  323.     }
  324.     if (s_pfn)
  325.         return s_pfn(dwUILevel, phwnd);
  326.     return INSTALLUILEVEL_NOCHANGE;
  327. }
  328. // MsiConfigureProduct
  329. typedef UINT (WINAPI * PFNMSICONFIGUREPRODUCT) (LPCTSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState);  
  330. /*----------------------------------------------------------
  331. Purpose: Thunk for NT 5's MsiConfigureProduct
  332. */
  333. UINT MSI_MsiConfigureProduct(LPCTSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
  334. {
  335.     static PFNMSICONFIGUREPRODUCT s_pfn = PFN_FIRSTTIME;
  336.     if (PFN_FIRSTTIME == s_pfn)
  337.     {
  338.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  339.         if (hinst)
  340.         {
  341.             // The unicode-decorated MSI APIs translate to ansi internally
  342.             // on Win95, so it should be safe to call them all the time.
  343. #ifdef UNICODE 
  344.             s_pfn = (PFNMSICONFIGUREPRODUCT)GetProcAddress(hinst, "MsiConfigureProductW");
  345. #else
  346.             s_pfn = (PFNMSICONFIGUREPRODUCT)GetProcAddress(hinst, "MsiConfigureProductA");
  347. #endif
  348.         }
  349.         else
  350.             s_pfn = NULL;
  351.     }
  352.     if (s_pfn)
  353.         return s_pfn(szProduct, iInstallLevel, eInstallState);
  354.     return ERROR_CALL_NOT_IMPLEMENTED;
  355. }
  356. // MsiQueryProductState
  357. typedef INSTALLSTATE (WINAPI * PFNMSIQUERYPRODUCTSTATE) (LPCTSTR szProductID);
  358. /*----------------------------------------------------------
  359. Purpose: Thunk for NT 5's MsiQueryProductState
  360. */
  361. INSTALLSTATE MSI_MsiQueryProductState(LPCTSTR szProductID)
  362. {
  363.     static PFNMSIQUERYPRODUCTSTATE s_pfn = PFN_FIRSTTIME;
  364.     if (PFN_FIRSTTIME == s_pfn)
  365.     {
  366.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  367.         if (hinst)
  368.         {
  369.             // The unicode-decorated MSI APIs translate to ansi internally
  370.             // on Win95, so it should be safe to call them all the time.
  371. #ifdef UNICODE 
  372.             s_pfn = (PFNMSIQUERYPRODUCTSTATE)GetProcAddress(hinst, "MsiQueryProductStateW");
  373. #else
  374.             s_pfn = (PFNMSIQUERYPRODUCTSTATE)GetProcAddress(hinst, "MsiQueryProductStateA");
  375. #endif
  376.         }
  377.         else
  378.             s_pfn = NULL;
  379.     }
  380.     if (s_pfn)
  381.         return s_pfn(szProductID);
  382.     return ERROR_CALL_NOT_IMPLEMENTED;
  383. }
  384. // MsiQueryFeatureState
  385. typedef INSTALLSTATE (WINAPI * PFNMSIQUERYFEATURESTATE) (LPCTSTR szProductID, LPCTSTR szFeature);
  386. /*----------------------------------------------------------
  387. Purpose: Thunk for NT 5's MsiQueryFeatureState
  388. */
  389. INSTALLSTATE MSI_MsiQueryFeatureState(LPCTSTR szProductID, LPCTSTR szFeature)
  390. {
  391.     static PFNMSIQUERYFEATURESTATE s_pfn = PFN_FIRSTTIME;
  392.     if (PFN_FIRSTTIME == s_pfn)
  393.     {
  394.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  395.         if (hinst)
  396.         {
  397.             // The unicode-decorated MSI APIs translate to ansi internally
  398.             // on Win95, so it should be safe to call them all the time.
  399. #ifdef UNICODE 
  400.             s_pfn = (PFNMSIQUERYFEATURESTATE)GetProcAddress(hinst, "MsiQueryFeatureStateW");
  401. #else
  402.             s_pfn = (PFNMSIQUERYFEATURESTATE)GetProcAddress(hinst, "MsiQueryFeatureStateA");
  403. #endif
  404.         }
  405.         else
  406.             s_pfn = NULL;
  407.     }
  408.     if (s_pfn)
  409.         return s_pfn(szProductID, szFeature);
  410.     return ERROR_CALL_NOT_IMPLEMENTED;
  411. }
  412. // MsiOpenPackage
  413. typedef UINT (WINAPI * PFNMSIOPENPACKAGE) (LPCTSTR szPackagePath, MSIHANDLE * hProduct);
  414. /*----------------------------------------------------------
  415. Purpose: Thunk for NT 5's MsiOpenPackage
  416. */
  417. UINT MSI_MsiOpenPackage(LPCTSTR szPackagePath, MSIHANDLE * hProduct)
  418. {
  419.     static PFNMSIOPENPACKAGE s_pfn = PFN_FIRSTTIME;
  420.     if (PFN_FIRSTTIME == s_pfn)
  421.     {
  422.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  423.         if (hinst)
  424.         {
  425.             // The unicode-decorated MSI APIs translate to ansi internally
  426.             // on Win95, so it should be safe to call them all the time.
  427. #ifdef UNICODE 
  428.             s_pfn = (PFNMSIOPENPACKAGE)GetProcAddress(hinst, "MsiOpenPackageW");
  429. #else
  430.             s_pfn = (PFNMSIOPENPACKAGE)GetProcAddress(hinst, "MsiOpenPackageA");
  431. #endif
  432.         }
  433.         else
  434.             s_pfn = NULL;
  435.     }
  436.     if (s_pfn)
  437.         return s_pfn(szPackagePath, hProduct);
  438.     return ERROR_CALL_NOT_IMPLEMENTED;
  439. }
  440. // MsiCloseHandle
  441. typedef UINT (WINAPI * PFNMSICLOSEHANDLE) (MSIHANDLE hAny);
  442. /*----------------------------------------------------------
  443. Purpose: Thunk for NT 5's MsiCloseHandle
  444. */
  445. UINT MSI_MsiCloseHandle(MSIHANDLE hAny)
  446. {
  447.     static PFNMSICLOSEHANDLE s_pfn = PFN_FIRSTTIME;
  448.     if (PFN_FIRSTTIME == s_pfn)
  449.     {
  450.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  451.         if (hinst)
  452.         {
  453.             s_pfn = (PFNMSICLOSEHANDLE)GetProcAddress(hinst, "MsiCloseHandle");
  454.         }
  455.         else
  456.             s_pfn = NULL;
  457.     }
  458.     if (s_pfn)
  459.         return s_pfn(hAny);
  460.     return ERROR_CALL_NOT_IMPLEMENTED;
  461. }
  462. // MsiDoAction
  463. typedef UINT (WINAPI * PFNMSIDOACTION) (MSIHANDLE hAny, LPCTSTR szAction);
  464. /*----------------------------------------------------------
  465. Purpose: Thunk for NT 5's MsiDoAction
  466. */
  467. UINT MSI_MsiDoAction(MSIHANDLE hAny, LPCTSTR szAction)
  468. {
  469.     static PFNMSIDOACTION s_pfn = PFN_FIRSTTIME;
  470.     if (PFN_FIRSTTIME == s_pfn)
  471.     {
  472.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  473.         if (hinst)
  474.         {
  475.             // The unicode-decorated MSI APIs translate to ansi internally
  476.             // on Win95, so it should be safe to call them all the time.
  477. #ifdef UNICODE 
  478.             s_pfn = (PFNMSIDOACTION)GetProcAddress(hinst, "MsiDoActionW");
  479. #else
  480.             s_pfn = (PFNMSIDOACTION)GetProcAddress(hinst, "MsiDoActionA");
  481. #endif
  482.         }
  483.         else
  484.             s_pfn = NULL;
  485.     }
  486.     if (s_pfn)
  487.         return s_pfn(hAny, szAction);
  488.     return ERROR_CALL_NOT_IMPLEMENTED;
  489. }
  490. // MsiGetFeatureCost
  491. typedef UINT (WINAPI * PFNMSIGETFEATURECOST) (MSIHANDLE hInstall, LPCTSTR szFeature, MSICOSTTREE  iCostTree, INSTALLSTATE iState, INT *piCost);
  492. /*----------------------------------------------------------
  493. Purpose: Thunk for NT 5's MsiGetFeatureCost
  494. */
  495. UINT MSI_MsiGetFeatureCost(MSIHANDLE hInstall, LPCTSTR szFeature, MSICOSTTREE  iCostTree, INSTALLSTATE iState, INT *piCost)
  496. {
  497.     static PFNMSIGETFEATURECOST s_pfn = PFN_FIRSTTIME;
  498.     if (PFN_FIRSTTIME == s_pfn)
  499.     {
  500.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  501.         if (hinst)
  502.         {
  503.             // The unicode-decorated MSI APIs translate to ansi internally
  504.             // on Win95, so it should be safe to call them all the time.
  505. #ifdef UNICODE 
  506.             s_pfn = (PFNMSIGETFEATURECOST)GetProcAddress(hinst, "MsiGetFeatureCostW");
  507. #else
  508.             s_pfn = (PFNMSIGETFEATURECOST)GetProcAddress(hinst, "MsiGetFeatureCostA");
  509. #endif
  510.         }
  511.         else
  512.             s_pfn = NULL;
  513.     }
  514.     if (s_pfn)
  515.         return s_pfn(hInstall, szFeature, iCostTree, iState, piCost);
  516.     return ERROR_CALL_NOT_IMPLEMENTED;
  517. }
  518. // MsiSetFeatureState
  519. typedef UINT (WINAPI * PFNMSISETFEATURESTATE) (MSIHANDLE hInstall, LPCTSTR szFeature, INSTALLSTATE iState);
  520. /*----------------------------------------------------------
  521. Purpose: Thunk for NT 5's MsiSetFeatureState
  522. */
  523. UINT MSI_MsiSetFeatureState(MSIHANDLE hInstall, LPCTSTR szFeature, INSTALLSTATE iState)
  524. {
  525.     static PFNMSISETFEATURESTATE s_pfn = PFN_FIRSTTIME;
  526.     if (PFN_FIRSTTIME == s_pfn)
  527.     {
  528.         HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  529.         if (hinst)
  530.         {
  531.             // The unicode-decorated MSI APIs translate to ansi internally
  532.             // on Win95, so it should be safe to call them all the time.
  533. #ifdef UNICODE 
  534.             s_pfn = (PFNMSISETFEATURESTATE)GetProcAddress(hinst, "MsiSetFeatureStateW");
  535. #else
  536.             s_pfn = (PFNMSISETFEATURESTATE)GetProcAddress(hinst, "MsiSetFeatureStateA");
  537. #endif
  538.         }
  539.         else
  540.             s_pfn = NULL;
  541.     }
  542.     if (s_pfn)
  543.         return s_pfn(hInstall, szFeature, iState);
  544.     return ERROR_CALL_NOT_IMPLEMENTED;
  545. }
  546. typedef HRESULT (__stdcall * PFNCSGETAPPCATEGORIES)(APPCATEGORYINFOLIST *pAppCategoryList);
  547. /*----------------------------------------------------------
  548. Purpose: Thunk for NT 5's CsGetAppCategories
  549. */
  550. HRESULT NT5_CsGetAppCategories(APPCATEGORYINFOLIST *pAppCategoryList)
  551. {
  552.     static PFNCSGETAPPCATEGORIES s_pfn = PFN_FIRSTTIME;
  553.     if (PFN_FIRSTTIME == s_pfn)
  554.     {
  555.         HINSTANCE hinst = LoadLibraryA("APPMGMTS.DLL");
  556.         if (hinst)
  557.             s_pfn = (PFNCSGETAPPCATEGORIES)GetProcAddress(hinst, "CsGetAppCategories");
  558.         else
  559.             s_pfn = NULL;
  560.     }
  561.     if (s_pfn)
  562.         return s_pfn(pAppCategoryList);
  563.     return E_NOTIMPL;    
  564. }
  565. typedef HRESULT (__stdcall * PFNRELEASEAPPCATEGORYINFOLIST)(APPCATEGORYINFOLIST *pAppCategoryList);
  566. /*----------------------------------------------------------
  567. Purpose: Thunk for NT 5's ReleaseAppCategoryInfoList
  568. */
  569. HRESULT NT5_ReleaseAppCategoryInfoList(APPCATEGORYINFOLIST *pAppCategoryList)
  570. {
  571.     static PFNRELEASEAPPCATEGORYINFOLIST s_pfn = PFN_FIRSTTIME;
  572.     if (PFN_FIRSTTIME == s_pfn)
  573.     {
  574.         HINSTANCE hinst = LoadLibraryA("APPMGMTS.DLL");
  575.         if (hinst)
  576.             s_pfn = (PFNRELEASEAPPCATEGORYINFOLIST)GetProcAddress(hinst, "ReleaseAppCategoryInfoList");
  577.         else
  578.             s_pfn = NULL;
  579.     }
  580.     if (s_pfn)
  581.         return s_pfn(pAppCategoryList);
  582.     return E_NOTIMPL;    
  583. }
  584. /*----------------------------------------------------------
  585. Purpose: Thunk for NT 5's AllowSetForegroundWindow
  586. */
  587. typedef UINT (WINAPI * PFNALLOWSFW) (DWORD dwPRocessID);  
  588. BOOL NT5_AllowSetForegroundWindow(DWORD dwProcessID)
  589. {
  590.     static PFNALLOWSFW s_pfn = PFN_FIRSTTIME;
  591.     if (PFN_FIRSTTIME == s_pfn)
  592.     {
  593.         HINSTANCE hinst = LoadLibraryA("USER32.DLL");
  594.         if (hinst)
  595.         {
  596.             s_pfn = (PFNALLOWSFW)GetProcAddress(hinst, "AllowSetForegroundWindow");
  597.         }
  598.         else
  599.             s_pfn = NULL;
  600.     }
  601.     if (s_pfn)
  602.         return s_pfn(dwProcessID);
  603.     return FALSE;
  604. }
  605. // InstallApplication
  606. typedef DWORD (WINAPI * PFNINSTALLAPP)(PINSTALLDATA pInstallInfo); 
  607. /*----------------------------------------------------------
  608. Purpose: Thunk for NT 5's InstallApplication
  609. */
  610. DWORD NT5_InstallApplication(PINSTALLDATA pInstallInfo)
  611. {
  612.     static PFNINSTALLAPP s_pfn = PFN_FIRSTTIME;
  613.     if (PFN_FIRSTTIME == s_pfn)
  614.     {
  615.         // It is safe to GetModuleHandle ADVAPI32 because we implicitly link
  616.         // to it, so it is guaranteed to be loaded in every thread.
  617.         
  618.         HINSTANCE hinst = GetModuleHandleA("ADVAPI32.DLL");
  619.         if (hinst)
  620.             s_pfn = (PFNINSTALLAPP)GetProcAddress(hinst, "InstallApplication");
  621.         else
  622.             s_pfn = NULL;
  623.     }
  624.     if (s_pfn)
  625.         return s_pfn(pInstallInfo);
  626.     return ERROR_INVALID_FUNCTION;       // failure
  627. }
  628. // UninstallApplication
  629. typedef DWORD (WINAPI * PFNUNINSTALLAPP)(WCHAR * pszProductCode); 
  630. /*----------------------------------------------------------
  631. Purpose: Thunk for NT 5's UninstallApplication
  632. */
  633. DWORD NT5_UninstallApplication(WCHAR * pszProductCode)
  634. {
  635.     static PFNUNINSTALLAPP s_pfn = PFN_FIRSTTIME;
  636.     if (PFN_FIRSTTIME == s_pfn)
  637.     {
  638.         // It is safe to GetModuleHandle ADVAPI32 because we implicitly link
  639.         // to it, so it is guaranteed to be loaded in every thread.
  640.         
  641.         HINSTANCE hinst = GetModuleHandleA("ADVAPI32.DLL");
  642.         if (hinst)
  643.             s_pfn = (PFNUNINSTALLAPP)GetProcAddress(hinst, "UninstallApplication");
  644.         else
  645.             s_pfn = NULL;
  646.     }
  647.     if (s_pfn)
  648.         return s_pfn(pszProductCode);
  649.     return ERROR_INVALID_FUNCTION;       // failure
  650. }
  651. // GetApplicationState
  652. typedef DWORD (WINAPI * PFNGETAPPSTATE)(WCHAR * ProductCode, APPSTATE * pAppState); 
  653. /*----------------------------------------------------------
  654. Purpose: Thunk for NT 5's GetApplicationState
  655. */
  656. DWORD NT5_GetApplicationState(WCHAR * pszProductCode, APPSTATE * pAppState)
  657. {
  658.     static PFNGETAPPSTATE s_pfn = PFN_FIRSTTIME;
  659.     if (PFN_FIRSTTIME == s_pfn)
  660.     {
  661.         // It is safe to GetModuleHandle ADVAPI32 because we implicitly link
  662.         // to it, so it is guaranteed to be loaded in every thread.
  663.         
  664.         HINSTANCE hinst = GetModuleHandleA("ADVAPI32.DLL");
  665.         if (hinst)
  666.             s_pfn = (PFNGETAPPSTATE)GetProcAddress(hinst, "GetApplicationState");
  667.         else
  668.             s_pfn = NULL;
  669.     }
  670.     if (s_pfn)
  671.         return s_pfn(pszProductCode, pAppState);
  672.     return ERROR_INVALID_FUNCTION;       // failure
  673. }
  674. // CommandLineFromMsiDescriptor
  675. typedef DWORD (WINAPI * PFNCMDLINE)(WCHAR * Descriptor, WCHAR * CommandLine, DWORD * CommandLineLength); 
  676. /*----------------------------------------------------------
  677. Purpose: Thunk for NT 5's CommandLineFromMsiDescriptor
  678. */
  679. DWORD NT5_CommandLineFromMsiDescriptor(WCHAR * pszDescriptor, WCHAR * pszCommandLine, DWORD * pcchCommandLine)
  680. {
  681.     static PFNCMDLINE s_pfn = PFN_FIRSTTIME;
  682.     if (PFN_FIRSTTIME == s_pfn)
  683.     {
  684.         // It is safe to GetModuleHandle ADVAPI32 because we implicitly link
  685.         // to it, so it is guaranteed to be loaded in every thread.
  686.         
  687.         HINSTANCE hinst = GetModuleHandleA("ADVAPI32.DLL");
  688.         if (hinst)
  689.             s_pfn = (PFNCMDLINE)GetProcAddress(hinst, "CommandLineFromMsiDescriptor");
  690.         else
  691.             s_pfn = NULL;
  692.     }
  693.     if (s_pfn)
  694.         return s_pfn(pszDescriptor, pszCommandLine, pcchCommandLine);
  695.     return ERROR_INVALID_FUNCTION;       // failure
  696. }
  697. // GetManagedApplications
  698. typedef DWORD (WINAPI * PFNGETAPPS)(GUID * pCategory, DWORD dwQueryFlags, DWORD dwInfoLevel, LPDWORD pdwApps, PMANAGEDAPPLICATION* prgManagedApps); 
  699. /*----------------------------------------------------------
  700. Purpose: Thunk for NT 5's GetManagedApplications
  701. */
  702. DWORD NT5_GetManagedApplications(GUID * pCategory, DWORD dwQueryFlags, DWORD dwInfoLevel, LPDWORD pdwApps, PMANAGEDAPPLICATION* prgManagedApps)
  703. {
  704.     static PFNGETAPPS s_pfn = PFN_FIRSTTIME;
  705.     if (PFN_FIRSTTIME == s_pfn)
  706.     {
  707.         // It is safe to GetModuleHandle ADVAPI32 because we implicitly link
  708.         // to it, so it is guaranteed to be loaded in every thread.
  709.         
  710.         HINSTANCE hinst = GetModuleHandleA("ADVAPI32.DLL");
  711.         if (hinst)
  712.             s_pfn = (PFNGETAPPS)GetProcAddress(hinst, "GetManagedApplications");
  713.         else
  714.             s_pfn = NULL;
  715.     }
  716.     if (s_pfn)
  717.         return s_pfn(pCategory, dwQueryFlags, dwInfoLevel, pdwApps, prgManagedApps);
  718.     return ERROR_INVALID_FUNCTION;       // failure
  719. }
  720. // NetGetJoinInformation
  721. typedef NET_API_STATUS (WINAPI * PFNGETJOININFO)(LPCWSTR lpServer, LPWSTR *lpNameBuffer, PNETSETUP_JOIN_STATUS  BufferType); 
  722. /*----------------------------------------------------------
  723. Purpose: Thunk for NT 5's NetGetJoinInformation
  724. */
  725. NET_API_STATUS NT5_NetGetJoinInformation(LPCWSTR lpServer, LPWSTR *lpNameBuffer, PNETSETUP_JOIN_STATUS  BufferType)
  726. {
  727.     static PFNGETJOININFO s_pfn = PFN_FIRSTTIME;
  728.     if (PFN_FIRSTTIME == s_pfn)
  729.     {
  730.         HINSTANCE hinst = LoadLibraryA("NETAPI32.DLL");
  731.         GetLastError();
  732.         if (hinst)
  733.             s_pfn = (PFNGETJOININFO)GetProcAddress(hinst, "NetGetJoinInformation");
  734.         else
  735.             s_pfn = NULL;
  736.     }
  737.     if (s_pfn)
  738.         return s_pfn(lpServer, lpNameBuffer, BufferType);
  739.     return NERR_NetNotStarted;       // failure
  740. }
  741. // NetApiBufferFree
  742. typedef NET_API_STATUS (WINAPI * PFNNETFREEBUFFER)(LPVOID lpBuffer); 
  743. /*----------------------------------------------------------
  744. Purpose: Thunk for NT 5's NetApiBufferFree
  745. */
  746. NET_API_STATUS NT5_NetApiBufferFree(LPVOID lpBuffer)
  747. {
  748.     static PFNNETFREEBUFFER s_pfn = PFN_FIRSTTIME;
  749.     if (PFN_FIRSTTIME == s_pfn)
  750.     {
  751.         HINSTANCE hinst = LoadLibraryA("NETAPI32.DLL");
  752.         if (hinst)
  753.             s_pfn = (PFNNETFREEBUFFER)GetProcAddress(hinst, "NetApiBufferFree");
  754.         else
  755.             s_pfn = NULL;
  756.     }
  757.     if (s_pfn)
  758.         return s_pfn(lpBuffer);
  759.     return NERR_NetNotStarted;       // failure
  760. }