Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

430 lines
13 KiB

  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. DWORD dwCompletionCode;
  41. PVOID pCompletionKey;
  42. LPOVERLAPPED lpOverlapped;
  43. while (TRUE)
  44. {
  45. // Wait for all the processes to finish...
  46. if (!GetQueuedCompletionStatus( hIOPort, &dwCompletionCode, (PULONG_PTR) &pCompletionKey,
  47. &lpOverlapped, INFINITE ) || (dwCompletionCode == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO))
  48. {
  49. break;
  50. }
  51. }
  52. return 0;
  53. }
  54. /*-------------------------------------------------------------------------
  55. Purpose: Creates a process and waits for it to finish
  56. */
  57. STDAPI_(BOOL) NT5_CreateAndWaitForProcess(LPTSTR pszExeName)
  58. {
  59. PROCESS_INFORMATION pi = {0};
  60. STARTUPINFO si = {0};
  61. BOOL fWorked = FALSE;
  62. #ifdef WX86
  63. DWORD cchArch;
  64. WCHAR szArchValue[32];
  65. #endif
  66. // CreateJobObject does not follow the win32 convention because even if the function succeeds, it can
  67. // still SetLastError to ERROR_ALREADY_EXISTS
  68. HANDLE hJob = CreateJobObject(NULL, c_szARPJob);
  69. if (hJob)
  70. {
  71. if (GetLastError() != ERROR_ALREADY_EXISTS)
  72. {
  73. HANDLE hIOPort = _SetJobCompletionPort(hJob);
  74. if (hIOPort)
  75. {
  76. DWORD dwCreationFlags = 0;
  77. // Create the install process
  78. si.cb = sizeof(si);
  79. #ifdef WX86
  80. if (bWx86Enabled && bForceX86Env) {
  81. cchArch = GetEnvironmentVariableW(ProcArchName,
  82. szArchValue,
  83. sizeof(szArchValue)
  84. );
  85. if (!cchArch || cchArch >= sizeof(szArchValue)) {
  86. szArchValue[0]=L'\0';
  87. }
  88. SetEnvironmentVariableW(ProcArchName, L"x86");
  89. }
  90. #endif
  91. dwCreationFlags = CREATE_SUSPENDED | CREATE_SEPARATE_WOW_VDM;
  92. // Create the process
  93. fWorked = CreateProcess(NULL, pszExeName, NULL, NULL, FALSE, dwCreationFlags, NULL, NULL, &si, &pi);
  94. if (fWorked)
  95. {
  96. HANDLE hWait = NULL;
  97. if (AssignProcessToJobObject(hJob, pi.hProcess))
  98. {
  99. hWait = CreateThread(NULL, 0, WaitingThreadProc, (LPVOID)hIOPort, 0, NULL);
  100. }
  101. if (hWait == NULL)
  102. {
  103. // We might get here if the call to AssignProcessToJobObject has failed because
  104. // the process already has a job assigned to it, or because we couldn't create the
  105. // waiting thread. Try a more direct approach by just watching the process handle.
  106. // This method won't catch spawned processes, but it is better than nothing.
  107. hWait = pi.hProcess;
  108. }
  109. else
  110. {
  111. // we are not waiting on the process handle, so we are done /w it.
  112. CloseHandle(pi.hProcess);
  113. }
  114. ResumeThread(pi.hThread);
  115. CloseHandle(pi.hThread);
  116. #ifdef WX86
  117. if (bWx86Enabled && bForceX86Env)
  118. {
  119. SetEnvironmentVariableW(ProcArchName, szArchValue);
  120. }
  121. #endif
  122. // we should have a valid handle at this point for sure
  123. ASSERT(hWait && (hWait != INVALID_HANDLE_VALUE));
  124. SHProcessSentMessagesUntilEvent(NULL, hWait, INFINITE);
  125. CloseHandle(hWait);
  126. }
  127. CloseHandle(hIOPort);
  128. }
  129. }
  130. CloseHandle(hJob);
  131. }
  132. return fWorked;
  133. }
  134. #define PFN_FIRSTTIME ((void *)-1)
  135. // VerSetConditionMask
  136. typedef ULONGLONG (WINAPI * PFNVERSETCONDITIONMASK)(ULONGLONG conditionMask, DWORD dwTypeMask, BYTE condition);
  137. /*----------------------------------------------------------
  138. Purpose: Thunk for NT 5's VerSetConditionMask
  139. */
  140. ULONGLONG NT5_VerSetConditionMask(ULONGLONG conditionMask, DWORD dwTypeMask, BYTE condition)
  141. {
  142. static PFNVERSETCONDITIONMASK s_pfn = PFN_FIRSTTIME;
  143. if (PFN_FIRSTTIME == s_pfn)
  144. {
  145. // It is safe to GetModuleHandle KERNEL32 because we implicitly link
  146. // to it, so it is guaranteed to be loaded in every thread.
  147. HINSTANCE hinst = GetModuleHandleA("KERNEL32.DLL");
  148. if (hinst)
  149. s_pfn = (PFNVERSETCONDITIONMASK)GetProcAddress(hinst, "VerSetConditionMask");
  150. else
  151. s_pfn = NULL;
  152. }
  153. if (s_pfn)
  154. return s_pfn(conditionMask, dwTypeMask, condition);
  155. return 0; // failure
  156. }
  157. typedef HRESULT (__stdcall * PFNRELEASEAPPCATEGORYINFOLIST)(APPCATEGORYINFOLIST *pAppCategoryList);
  158. /*----------------------------------------------------------
  159. Purpose: Thunk for NT 5's ReleaseAppCategoryInfoList
  160. */
  161. HRESULT NT5_ReleaseAppCategoryInfoList(APPCATEGORYINFOLIST *pAppCategoryList)
  162. {
  163. static PFNRELEASEAPPCATEGORYINFOLIST s_pfn = PFN_FIRSTTIME;
  164. if (PFN_FIRSTTIME == s_pfn)
  165. {
  166. HINSTANCE hinst = LoadLibraryA("APPMGMTS.DLL");
  167. if (hinst)
  168. s_pfn = (PFNRELEASEAPPCATEGORYINFOLIST)GetProcAddress(hinst, "ReleaseAppCategoryInfoList");
  169. else
  170. s_pfn = NULL;
  171. }
  172. if (s_pfn)
  173. return s_pfn(pAppCategoryList);
  174. return E_NOTIMPL;
  175. }
  176. /*----------------------------------------------------------
  177. Purpose: Thunk for NT 5's AllowSetForegroundWindow
  178. */
  179. typedef UINT (WINAPI * PFNALLOWSFW) (DWORD dwPRocessID);
  180. BOOL NT5_AllowSetForegroundWindow(DWORD dwProcessID)
  181. {
  182. static PFNALLOWSFW s_pfn = PFN_FIRSTTIME;
  183. if (PFN_FIRSTTIME == s_pfn)
  184. {
  185. HINSTANCE hinst = LoadLibraryA("USER32.DLL");
  186. if (hinst)
  187. {
  188. s_pfn = (PFNALLOWSFW)GetProcAddress(hinst, "AllowSetForegroundWindow");
  189. }
  190. else
  191. s_pfn = NULL;
  192. }
  193. if (s_pfn)
  194. return s_pfn(dwProcessID);
  195. return FALSE;
  196. }
  197. // InstallApplication
  198. typedef DWORD (WINAPI * PFNINSTALLAPP)(PINSTALLDATA pInstallInfo);
  199. /*----------------------------------------------------------
  200. Purpose: Thunk for NT 5's InstallApplication
  201. */
  202. DWORD NT5_InstallApplication(PINSTALLDATA pInstallInfo)
  203. {
  204. static PFNINSTALLAPP s_pfn = PFN_FIRSTTIME;
  205. if (PFN_FIRSTTIME == s_pfn)
  206. {
  207. // It is safe to GetModuleHandle ADVAPI32 because we implicitly link
  208. // to it, so it is guaranteed to be loaded in every thread.
  209. HINSTANCE hinst = GetModuleHandleA("ADVAPI32.DLL");
  210. if (hinst)
  211. s_pfn = (PFNINSTALLAPP)GetProcAddress(hinst, "InstallApplication");
  212. else
  213. s_pfn = NULL;
  214. }
  215. if (s_pfn)
  216. return s_pfn(pInstallInfo);
  217. return ERROR_INVALID_FUNCTION; // failure
  218. }
  219. // UninstallApplication
  220. typedef DWORD (WINAPI * PFNUNINSTALLAPP)(WCHAR * pszProductCode, DWORD dwStatus);
  221. /*----------------------------------------------------------
  222. Purpose: Thunk for NT 5's UninstallApplication
  223. */
  224. DWORD NT5_UninstallApplication(WCHAR * pszProductCode, DWORD dwStatus)
  225. {
  226. static PFNUNINSTALLAPP s_pfn = PFN_FIRSTTIME;
  227. if (PFN_FIRSTTIME == s_pfn)
  228. {
  229. // It is safe to GetModuleHandle ADVAPI32 because we implicitly link
  230. // to it, so it is guaranteed to be loaded in every thread.
  231. HINSTANCE hinst = GetModuleHandleA("ADVAPI32.DLL");
  232. if (hinst)
  233. s_pfn = (PFNUNINSTALLAPP)GetProcAddress(hinst, "UninstallApplication");
  234. else
  235. s_pfn = NULL;
  236. }
  237. if (s_pfn)
  238. return s_pfn(pszProductCode, dwStatus);
  239. return ERROR_INVALID_FUNCTION; // failure
  240. }
  241. // GetManagedApplications
  242. typedef DWORD (WINAPI * PFNGETAPPS)(GUID * pCategory, DWORD dwQueryFlags, DWORD dwInfoLevel, LPDWORD pdwApps, PMANAGEDAPPLICATION* prgManagedApps);
  243. /*----------------------------------------------------------
  244. Purpose: Thunk for NT 5's GetManagedApplications
  245. */
  246. DWORD NT5_GetManagedApplications(GUID * pCategory, DWORD dwQueryFlags, DWORD dwInfoLevel, LPDWORD pdwApps, PMANAGEDAPPLICATION* prgManagedApps)
  247. {
  248. static PFNGETAPPS s_pfn = PFN_FIRSTTIME;
  249. if (PFN_FIRSTTIME == s_pfn)
  250. {
  251. // It is safe to GetModuleHandle ADVAPI32 because we implicitly link
  252. // to it, so it is guaranteed to be loaded in every thread.
  253. HINSTANCE hinst = GetModuleHandleA("ADVAPI32.DLL");
  254. if (hinst)
  255. s_pfn = (PFNGETAPPS)GetProcAddress(hinst, "GetManagedApplications");
  256. else
  257. s_pfn = NULL;
  258. }
  259. if (s_pfn)
  260. return s_pfn(pCategory, dwQueryFlags, dwInfoLevel, pdwApps, prgManagedApps);
  261. return ERROR_INVALID_FUNCTION; // failure
  262. }
  263. typedef DWORD (__stdcall * PFNGETMANAGEDAPPLICATIONCATEGORIES)(DWORD dwReserved, APPCATEGORYINFOLIST *pAppCategoryList);
  264. /*----------------------------------------------------------
  265. Purpose: Thunk for NT 5's CsGetAppCategories
  266. */
  267. DWORD NT5_GetManagedApplicationCategories(DWORD dwReserved, APPCATEGORYINFOLIST *pAppCategoryList)
  268. {
  269. static PFNGETMANAGEDAPPLICATIONCATEGORIES s_pfn = PFN_FIRSTTIME;
  270. if (PFN_FIRSTTIME == s_pfn)
  271. {
  272. HINSTANCE hinst = LoadLibraryA("ADVAPI32.DLL");
  273. if (hinst)
  274. s_pfn = (PFNGETMANAGEDAPPLICATIONCATEGORIES)GetProcAddress(hinst, "GetManagedApplicationCategories");
  275. else
  276. s_pfn = NULL;
  277. }
  278. if (s_pfn)
  279. return s_pfn(dwReserved, pAppCategoryList);
  280. return ERROR_INVALID_FUNCTION;
  281. }
  282. // NetGetJoinInformation
  283. typedef NET_API_STATUS (WINAPI * PFNGETJOININFO)(LPCWSTR lpServer, LPWSTR *lpNameBuffer, PNETSETUP_JOIN_STATUS BufferType);
  284. /*----------------------------------------------------------
  285. Purpose: Thunk for NT 5's NetGetJoinInformation
  286. */
  287. NET_API_STATUS NT5_NetGetJoinInformation(LPCWSTR lpServer, LPWSTR *lpNameBuffer, PNETSETUP_JOIN_STATUS BufferType)
  288. {
  289. static PFNGETJOININFO s_pfn = PFN_FIRSTTIME;
  290. if (PFN_FIRSTTIME == s_pfn)
  291. {
  292. HINSTANCE hinst = LoadLibraryA("NETAPI32.DLL");
  293. if (hinst)
  294. s_pfn = (PFNGETJOININFO)GetProcAddress(hinst, "NetGetJoinInformation");
  295. else
  296. s_pfn = NULL;
  297. }
  298. if (s_pfn)
  299. return s_pfn(lpServer, lpNameBuffer, BufferType);
  300. return NERR_NetNotStarted; // failure
  301. }
  302. // NetApiBufferFree
  303. typedef NET_API_STATUS (WINAPI * PFNNETFREEBUFFER)(LPVOID lpBuffer);
  304. /*----------------------------------------------------------
  305. Purpose: Thunk for NT 5's NetApiBufferFree
  306. */
  307. NET_API_STATUS NT5_NetApiBufferFree(LPVOID lpBuffer)
  308. {
  309. static PFNNETFREEBUFFER s_pfn = PFN_FIRSTTIME;
  310. if (PFN_FIRSTTIME == s_pfn)
  311. {
  312. HINSTANCE hinst = LoadLibraryA("NETAPI32.DLL");
  313. if (hinst)
  314. s_pfn = (PFNNETFREEBUFFER)GetProcAddress(hinst, "NetApiBufferFree");
  315. else
  316. s_pfn = NULL;
  317. }
  318. if (s_pfn)
  319. return s_pfn(lpBuffer);
  320. return NERR_NetNotStarted; // failure
  321. }