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.

1783 lines
48 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WSHELL.C
  8. * WOW32 16-bit SHELL API support
  9. *
  10. * History:
  11. * 14-April-1992 Chandan Chauhan (ChandanC)
  12. * Created.
  13. *
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include <winreg.h>
  18. #include "wowshlp.h"
  19. MODNAME(wshell.c);
  20. LONG
  21. WOWRegDeleteKey(
  22. IN HKEY hKey,
  23. IN LPCTSTR lpszSubKey
  24. );
  25. #ifndef WIN16_HKEY_CLASSES_ROOT
  26. #define WIN16_HKEY_CLASSES_ROOT 1
  27. #endif
  28. #ifndef WIN16_ERROR_SUCCESS
  29. #define WIN16_ERROR_SUCCESS 0L
  30. #define WIN16_ERROR_BADDB 1L
  31. #define WIN16_ERROR_BADKEY 2L
  32. #define WIN16_ERROR_CANTOPEN 3L
  33. #define WIN16_ERROR_CANTREAD 4L
  34. #define WIN16_ERROR_CANTWRITE 5L
  35. #define WIN16_ERROR_OUTOFMEMORY 6L
  36. #define WIN16_ERROR_INVALID_PARAMETER 7L
  37. #define WIN16_ERROR_ACCESS_DENIED 8L
  38. #endif
  39. //
  40. // Flags for DROPALIAS's dwFlags member
  41. //
  42. #define ALLOC_H32 0x0001L
  43. #define ALLOC_H16 0x0002L
  44. ULONG FASTCALL WS32DoEnvironmentSubst(PVDMFRAME pFrame)
  45. {
  46. //
  47. // This is an undocumented shell.dll API used by ProgMan
  48. // and Norton AntiVirus for Windows (part of Norton
  49. // Desktop for Windows), probably among others.
  50. // Since it's not in the Win32 shellapi.h, we have a
  51. // copy of the prototype here, copied from
  52. // \nt\private\windows\shell\library\expenv.c.
  53. //
  54. ULONG ul;
  55. register PDOENVIRONMENTSUBST16 parg16;
  56. PSZ psz;
  57. WORD cch;
  58. PSZ pszExpanded;
  59. DWORD cchExpanded;
  60. GETARGPTR(pFrame, sizeof(DOENVIRONMENTSUBST16), parg16);
  61. GETPSZPTR(parg16->vpsz, psz);
  62. cch = FETCHWORD(parg16->cch);
  63. LOGDEBUG(0,("WS32DoEnvironmentSubst input: '%s'\n", psz));
  64. //
  65. // DoEnvironmentSubst makes its substitution in an allocated
  66. // buffer of cch characters. If the substution is too long
  67. // to fit, the original string is left untouched and the
  68. // low word of the return is FALSE, the high word is the
  69. // value of cch. If it fits, the string is overlaid and
  70. // the low word of the return is TRUE, and the high word
  71. // is the length (strlen()-style) of the expanded string.
  72. //
  73. if (!(pszExpanded = malloc_w(cch * sizeof(*psz)))) {
  74. goto Fail;
  75. }
  76. cchExpanded = ExpandEnvironmentStrings(
  77. psz, // source
  78. pszExpanded, // dest.
  79. cch // dest. size
  80. );
  81. if (cchExpanded <= (DWORD)cch) {
  82. //
  83. // Succeeded, copy expanded string to caller's buffer.
  84. // cchExpanded includes null terminator, our return
  85. // code doesn't.
  86. //
  87. RtlCopyMemory(psz, pszExpanded, cchExpanded);
  88. LOGDEBUG(0,("WS32DoEnvironmentSubst output: '%s'\n", psz));
  89. WOW32ASSERT((cchExpanded - 1) == strlen(psz));
  90. FLUSHVDMPTR(parg16->vpsz, (USHORT)cchExpanded, psz);
  91. ul = MAKELONG((WORD)(cchExpanded - 1), TRUE);
  92. } else {
  93. Fail:
  94. ul = MAKELONG((WORD)cch, FALSE);
  95. LOGDEBUG(0,("WS32DoEnvironmentSubst failing!!!\n"));
  96. }
  97. if (pszExpanded) {
  98. free_w(pszExpanded);
  99. }
  100. FREEPSZPTR(psz);
  101. FREEARGPTR(parg16);
  102. RETURN(ul);
  103. }
  104. ULONG FASTCALL WS32RegOpenKey(PVDMFRAME pFrame)
  105. {
  106. ULONG ul;
  107. register PREGOPENKEY16 parg16;
  108. HKEY hkResult = 0;
  109. HKEY hkey;
  110. PSZ psz;
  111. PSZ psz1 = NULL;
  112. PHKEY lp;
  113. GETARGPTR(pFrame, sizeof(REGOPENKEY16), parg16);
  114. GETPSZPTR(parg16->f2, psz);
  115. GETOPTPTR(parg16->f3, 0, lp);
  116. hkey = (HKEY)FETCHDWORD(parg16->f1);
  117. if ((DWORD)hkey == WIN16_HKEY_CLASSES_ROOT) {
  118. hkey = (HKEY)HKEY_CLASSES_ROOT;
  119. }
  120. if (!hkey) {
  121. if (psz) {
  122. psz1 = Remove_Classes (psz);
  123. }
  124. ul = DPM_RegOpenKey (
  125. HKEY_CLASSES_ROOT,
  126. psz1,
  127. &hkResult
  128. );
  129. if ((psz1) && (psz1 != psz)) {
  130. free_w (psz1);
  131. }
  132. }
  133. else {
  134. ul = DPM_RegOpenKey (
  135. hkey,
  136. psz,
  137. &hkResult
  138. );
  139. }
  140. if(lp) {
  141. STOREDWORD(*lp, hkResult);
  142. FLUSHVDMPTR(parg16->f3, 4, lp);
  143. }
  144. ul = ConvertToWin31Error(ul);
  145. FREEOPTPTR(lp);
  146. FREEPSZPTR(psz);
  147. FREEARGPTR(parg16);
  148. RETURN(ul);
  149. }
  150. ULONG FASTCALL WS32RegCreateKey(PVDMFRAME pFrame)
  151. {
  152. ULONG ul;
  153. register PREGCREATEKEY16 parg16;
  154. PSZ psz;
  155. PSZ psz1 = NULL;
  156. HKEY hkResult = 0;
  157. HKEY hkey;
  158. PHKEY lp;
  159. GETARGPTR(pFrame, sizeof(REGCREATEKEY16), parg16);
  160. GETPSZPTR(parg16->f2, psz);
  161. GETOPTPTR(parg16->f3, 0, lp);
  162. hkey = (HKEY)FETCHDWORD(parg16->f1);
  163. if ((DWORD)hkey == WIN16_HKEY_CLASSES_ROOT) {
  164. hkey = (HKEY)HKEY_CLASSES_ROOT;
  165. }
  166. if (!hkey) {
  167. if (psz) {
  168. psz1 = Remove_Classes (psz);
  169. }
  170. ul = DPM_RegCreateKey (
  171. HKEY_CLASSES_ROOT,
  172. psz1,
  173. &hkResult
  174. );
  175. if ((psz1) && (psz1 != psz)) {
  176. free_w (psz1);
  177. }
  178. }
  179. else {
  180. ul = DPM_RegCreateKey (
  181. hkey,
  182. psz,
  183. &hkResult
  184. );
  185. }
  186. if(lp) {
  187. STOREDWORD(*lp, hkResult);
  188. FLUSHVDMPTR(parg16->f3, 4, lp);
  189. }
  190. ul = ConvertToWin31Error(ul);
  191. FREEOPTPTR(lp);
  192. FREEPSZPTR(psz);
  193. FREEARGPTR(parg16);
  194. RETURN(ul);
  195. }
  196. ULONG FASTCALL WS32RegCloseKey(PVDMFRAME pFrame)
  197. {
  198. ULONG ul;
  199. register PREGCLOSEKEY16 parg16;
  200. HKEY hkey;
  201. GETARGPTR(pFrame, sizeof(REGCLOSEKEY16), parg16);
  202. hkey = (HKEY)FETCHDWORD(parg16->f1);
  203. if ((DWORD)hkey == WIN16_HKEY_CLASSES_ROOT) {
  204. hkey = (HKEY)HKEY_CLASSES_ROOT;
  205. }
  206. ul = DPM_RegCloseKey (
  207. hkey
  208. );
  209. ul = ConvertToWin31Error(ul);
  210. FREEARGPTR(parg16);
  211. RETURN(ul);
  212. }
  213. ULONG FASTCALL WS32RegDeleteKey(PVDMFRAME pFrame)
  214. {
  215. ULONG ul;
  216. register PREGDELETEKEY16 parg16;
  217. HKEY hkey;
  218. PSZ psz;
  219. PSZ psz1 = NULL;
  220. GETARGPTR(pFrame, sizeof(REGDELETEKEY16), parg16);
  221. GETPSZPTR(parg16->f2, psz);
  222. hkey = (HKEY)FETCHDWORD(parg16->f1);
  223. if ((DWORD)hkey == WIN16_HKEY_CLASSES_ROOT) {
  224. hkey = (HKEY)HKEY_CLASSES_ROOT;
  225. }
  226. //
  227. // Fail any attempt to RegDeleteKey(something, NULL),
  228. // with ERROR_BADKEY as Win3.1 does.
  229. //
  230. if ((!psz) || (*psz == '\0')) {
  231. ul = ERROR_BADKEY;
  232. } else {
  233. if (!hkey) {
  234. psz1 = Remove_Classes (psz);
  235. ul = WOWRegDeleteKey (
  236. HKEY_CLASSES_ROOT,
  237. psz1
  238. );
  239. if ((psz1) && (psz1 != psz)) {
  240. free_w (psz1);
  241. }
  242. } else {
  243. ul = WOWRegDeleteKey (
  244. hkey,
  245. psz
  246. );
  247. }
  248. }
  249. ul = ConvertToWin31Error(ul);
  250. FREEPSZPTR(psz);
  251. FREEARGPTR(parg16);
  252. RETURN(ul);
  253. }
  254. LONG
  255. APIENTRY
  256. WOWRegDeleteKey(
  257. HKEY hKey,
  258. LPCSTR lpszSubKey
  259. )
  260. /*++
  261. Routine Description:
  262. There is a significant difference between the Win3.1 and Win32
  263. behavior of RegDeleteKey when the key in question has subkeys.
  264. The Win32 API does not allow you to delete a key with subkeys,
  265. while the Win3.1 API deletes a key and all its subkeys.
  266. This routine is a recursive worker that enumerates the subkeys
  267. of a given key, applies itself to each one, then deletes itself.
  268. It specifically does not attempt to deal rationally with the
  269. case where the caller may not have access to some of the subkeys
  270. of the key to be deleted. In this case, all the subkeys which
  271. the caller can delete will be deleted, but the api will still
  272. return ERROR_ACCESS_DENIED.
  273. Arguments:
  274. hKey - Supplies a handle to an open registry key.
  275. lpszSubKey - Supplies the name of a subkey which is to be deleted
  276. along with all of its subkeys.
  277. Return Value:
  278. ERROR_SUCCESS - entire subtree successfully deleted.
  279. ERROR_ACCESS_DENIED - given subkey could not be deleted.
  280. --*/
  281. {
  282. DWORD i;
  283. HKEY Key;
  284. LONG Status;
  285. DWORD ClassLength=0;
  286. DWORD SubKeys;
  287. DWORD MaxSubKey;
  288. DWORD MaxClass;
  289. DWORD Values;
  290. DWORD MaxValueName;
  291. DWORD MaxValueData;
  292. DWORD SecurityLength;
  293. FILETIME LastWriteTime;
  294. LPTSTR NameBuffer;
  295. //
  296. // First open the given key so we can enumerate its subkeys
  297. //
  298. Status = DPM_RegOpenKeyEx(hKey,
  299. lpszSubKey,
  300. 0,
  301. KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
  302. &Key);
  303. if (Status != ERROR_SUCCESS) {
  304. //
  305. // possibly we have delete access, but not enumerate/query.
  306. // So go ahead and try the delete call, but don't worry about
  307. // any subkeys. If we have any, the delete will fail anyway.
  308. //
  309. return(DPM_RegDeleteKey(hKey,lpszSubKey));
  310. }
  311. //
  312. // Use RegQueryInfoKey to determine how big to allocate the buffer
  313. // for the subkey names.
  314. //
  315. Status = DPM_RegQueryInfoKey(Key,
  316. NULL,
  317. &ClassLength,
  318. 0,
  319. &SubKeys,
  320. &MaxSubKey,
  321. &MaxClass,
  322. &Values,
  323. &MaxValueName,
  324. &MaxValueData,
  325. &SecurityLength,
  326. &LastWriteTime);
  327. if ((Status != ERROR_SUCCESS) &&
  328. (Status != ERROR_MORE_DATA) &&
  329. (Status != ERROR_INSUFFICIENT_BUFFER)) {
  330. DPM_RegCloseKey(Key);
  331. return(Status);
  332. }
  333. NameBuffer = malloc_w(MaxSubKey + 1);
  334. if (NameBuffer == NULL) {
  335. DPM_RegCloseKey(Key);
  336. return(ERROR_NOT_ENOUGH_MEMORY);
  337. }
  338. //
  339. // Enumerate subkeys and apply ourselves to each one.
  340. //
  341. i=0;
  342. do {
  343. Status = DPM_RegEnumKey(Key,
  344. i,
  345. NameBuffer,
  346. MaxSubKey+1);
  347. if (Status == ERROR_SUCCESS) {
  348. Status = WOWRegDeleteKey(Key,NameBuffer);
  349. }
  350. if (Status != ERROR_SUCCESS) {
  351. //
  352. // Failed to delete the key at the specified index. Increment
  353. // the index and keep going. We could probably bail out here,
  354. // since the api is going to fail, but we might as well keep
  355. // going and delete everything we can.
  356. //
  357. ++i;
  358. }
  359. } while ( (Status != ERROR_NO_MORE_ITEMS) &&
  360. (i < SubKeys) );
  361. free_w(NameBuffer);
  362. DPM_RegCloseKey(Key);
  363. return(DPM_RegDeleteKey(hKey,lpszSubKey));
  364. }
  365. // This is a Win 9x API. It doesn't need some of the thunking required by
  366. // the Win 3.1 Regxxx() API's. ie. WIN16_HKEY_CLASSES_ROOT conversion &
  367. // ConvertToWin31Error().
  368. // Since this was brought over from the interpreted thunk code, it doesn't
  369. // require any special thunking for any of the parameters until an issue is
  370. // identified -- at which time this comment should be removed.
  371. ULONG FASTCALL WS32RegDeleteValue(PVDMFRAME pFrame)
  372. {
  373. ULONG ul;
  374. register PREGDELETEVALUE3216 parg16;
  375. HKEY hkey;
  376. PSZ lpszValueName;
  377. GETARGPTR(pFrame, sizeof(REGDELETEVALUE3216), parg16);
  378. hkey = (HKEY)FETCHDWORD(parg16->hKey);
  379. GETPSZPTR(parg16->lpszValue, lpszValueName);
  380. ul = DPM_RegDeleteValue (hkey,
  381. lpszValueName);
  382. FREEPSZPTR(lpszValueName);
  383. FREEARGPTR(parg16);
  384. RETURN(ul);
  385. }
  386. // This is a Win 9x API. It doesn't need some of the thunking required by
  387. // the Win 3.1 Regxxx() API's. ie. WIN16_HKEY_CLASSES_ROOT conversion &
  388. // ConvertToWin31Error().
  389. // Since this was brought over from the interpreted thunk code, it doesn't
  390. // require any special thunking for any of the parameters until an issue is
  391. // identified -- at which time this comment should be removed.
  392. ULONG FASTCALL WS32RegFlushKey(PVDMFRAME pFrame)
  393. {
  394. ULONG ul;
  395. register PREGFLUSHKEY3216 parg16;
  396. HKEY hkey;
  397. GETARGPTR(pFrame, sizeof(REGFLUSHKEY3216), parg16);
  398. hkey = (HKEY)FETCHDWORD(parg16->hKey);
  399. ul = DPM_RegFlushKey (hkey);
  400. FREEARGPTR(parg16);
  401. RETURN(ul);
  402. }
  403. // This is a Win 9x API. It doesn't need some of the thunking required by
  404. // the Win 3.1 Regxxx() API's. ie. WIN16_HKEY_CLASSES_ROOT conversion &
  405. // ConvertToWin31Error().
  406. // Since this was brought over from the interpreted thunk code, it doesn't
  407. // require any special thunking for any of the parameters until an issue is
  408. // identified -- at which time this comment should be removed.
  409. ULONG FASTCALL WS32RegLoadKey(PVDMFRAME pFrame)
  410. {
  411. ULONG ul;
  412. register PREGLOADKEY3216 parg16;
  413. HKEY hkey;
  414. PSZ lpszSubKey, lpszFile;
  415. GETARGPTR(pFrame, sizeof(REGLOADKEY3216), parg16);
  416. hkey = (HKEY)FETCHDWORD(parg16->hKey);
  417. GETPSZPTR(parg16->lpszSubkey, lpszSubKey);
  418. GETPSZPTR(parg16->lpszFileName, lpszFile);
  419. ul = DPM_RegLoadKey (hkey,
  420. lpszSubKey,
  421. lpszFile);
  422. FREEPSZPTR(lpszSubKey);
  423. FREEPSZPTR(lpszFile);
  424. FREEARGPTR(parg16);
  425. RETURN(ul);
  426. }
  427. // This is a Win 9x API. It doesn't need some of the thunking required by
  428. // the Win 3.1 Regxxx() API's. ie. WIN16_HKEY_CLASSES_ROOT conversion &
  429. // ConvertToWin31Error().
  430. // Since this was brought over from the interpreted thunk code, it doesn't
  431. // require any special thunking for any of the parameters until an issue is
  432. // identified -- at which time this comment should be removed.
  433. ULONG FASTCALL WS32RegUnLoadKey(PVDMFRAME pFrame)
  434. {
  435. ULONG ul;
  436. register PREGUNLOADKEY3216 parg16;
  437. HKEY hkey;
  438. PSZ lpszSubKey;
  439. GETARGPTR(pFrame, sizeof(REGUNLOADKEY3216), parg16);
  440. hkey = (HKEY)FETCHDWORD(parg16->hKey);
  441. GETPSZPTR(parg16->lpszSubkey, lpszSubKey);
  442. ul = DPM_RegUnLoadKey (hkey,
  443. lpszSubKey);
  444. FREEPSZPTR(lpszSubKey);
  445. FREEARGPTR(parg16);
  446. RETURN(ul);
  447. }
  448. // This is a Win 9x API. It doesn't need some of the thunking required by
  449. // the Win 3.1 Regxxx() API's. ie. WIN16_HKEY_CLASSES_ROOT conversion &
  450. // ConvertToWin31Error().
  451. // Since this was brought over from the interpreted thunk code, it doesn't
  452. // require any special thunking for any of the parameters until an issue is
  453. // identified -- at which time this comment should be removed.
  454. ULONG FASTCALL WS32RegSaveKey(PVDMFRAME pFrame)
  455. {
  456. ULONG ul;
  457. register PREGSAVEKEY3216 parg16;
  458. HKEY hkey;
  459. PSZ lpszFile;
  460. LPSECURITY_ATTRIBUTES lpSecurityAttributes;
  461. GETARGPTR(pFrame, sizeof(REGSAVEKEY3216), parg16);
  462. hkey = (HKEY)FETCHDWORD(parg16->hKey);
  463. GETPSZPTR(parg16->lpszFile, lpszFile);
  464. GETOPTPTR(parg16->lpSA, sizeof(SECURITY_ATTRIBUTES), lpSecurityAttributes);
  465. ul = DPM_RegSaveKey (hkey,
  466. lpszFile,
  467. lpSecurityAttributes);
  468. FREEPSZPTR(lpszFile);
  469. FREEOPTPTR(lpSecurityAttributes);
  470. FREEARGPTR(parg16);
  471. RETURN(ul);
  472. }
  473. ULONG FASTCALL WS32RegSetValue(PVDMFRAME pFrame)
  474. {
  475. register PREGSETVALUE16 parg16;
  476. ULONG ul;
  477. CHAR szZero[] = { '0', '\0' };
  478. HKEY hkey;
  479. PSZ psz2;
  480. PSZ psz1 = NULL;
  481. LPBYTE lpszData = NULL;
  482. GETARGPTR(pFrame, sizeof(REGSETVALUE16), parg16);
  483. // Do what Win 3.1 does
  484. if(parg16->f3 != REG_SZ) {
  485. FREEARGPTR(parg16);
  486. return(WIN16_ERROR_INVALID_PARAMETER);
  487. }
  488. GETOPTPTR(parg16->f2, 0, psz2);
  489. // Windows 3.1 API reference says that cb (f5) is ignored.
  490. // Ergo, remove it from this call and use 1 in its place
  491. // (1 being the smallest size of a sz string)
  492. if(parg16->f4) {
  493. GETOPTPTR(parg16->f4, 1, lpszData);
  494. }
  495. // Quattro Pro 6.0 Install passes lpszData == NULL
  496. // In Win3.1, if(!lpszData || *lpszData == '\0') the value is set to 0
  497. if(!lpszData) {
  498. lpszData = szZero;
  499. }
  500. hkey = (HKEY)FETCHDWORD(parg16->f1);
  501. if ((DWORD)hkey == WIN16_HKEY_CLASSES_ROOT) {
  502. hkey = (HKEY)HKEY_CLASSES_ROOT;
  503. }
  504. if (!hkey) {
  505. if (psz2) {
  506. psz1 = Remove_Classes (psz2);
  507. }
  508. ul = DPM_RegSetValue (HKEY_CLASSES_ROOT,
  509. psz1,
  510. REG_SZ,
  511. lpszData,
  512. lstrlen(lpszData));
  513. if ((psz1) && (psz1 != psz2)) {
  514. free_w (psz1);
  515. }
  516. }
  517. else {
  518. ul = DPM_RegSetValue (hkey,
  519. psz2,
  520. REG_SZ,
  521. lpszData,
  522. lstrlen(lpszData));
  523. }
  524. ul = ConvertToWin31Error(ul);
  525. FREEOPTPTR(psz2);
  526. FREEOPTPTR(lpszData);
  527. FREEARGPTR(parg16);
  528. RETURN(ul);
  529. }
  530. // This is a Win 9x API. It doesn't need some of the thunking required by
  531. // the Win 3.1 Regxxx() API's. ie. WIN16_HKEY_CLASSES_ROOT conversion &
  532. // ConvertToWin31Error().
  533. // Since this was brought over from the interpreted thunk code, it doesn't
  534. // require any special thunking for any of the parameters until an issue is
  535. // identified -- at which time this comment should be removed.
  536. ULONG FASTCALL WS32RegSetValueEx(PVDMFRAME pFrame)
  537. {
  538. register PREGSETVALUEEX3216 parg16;
  539. ULONG ul;
  540. HKEY hkey;
  541. PSZ lpszValueName;
  542. LPBYTE lpData;
  543. GETARGPTR(pFrame, sizeof(REGSETVALUE3216), parg16);
  544. hkey = (HKEY)FETCHDWORD(parg16->hKey);
  545. GETOPTPTR(parg16->lpszValue, 0, lpszValueName);
  546. GETOPTPTR(parg16->lpBuffer, parg16->cbBuffer, lpData);
  547. ul = DPM_RegSetValueEx(hkey,
  548. lpszValueName,
  549. parg16->dwReserved,
  550. parg16->dwType,
  551. lpData,
  552. parg16->cbBuffer);
  553. FREEOPTPTR(lpszValueName);
  554. FREEOPTPTR(lpData);
  555. FREEARGPTR(parg16);
  556. RETURN(ul);
  557. }
  558. ULONG FASTCALL WS32RegQueryValue(PVDMFRAME pFrame)
  559. {
  560. ULONG ul;
  561. register PREGQUERYVALUE16 parg16;
  562. HKEY hkey;
  563. PSZ psz1 = NULL;
  564. PSZ psz2;
  565. LPBYTE lpszData;
  566. LPDWORD lpcbValue;
  567. DWORD cbValue;
  568. #define QUERYBUFFERSIZE 128
  569. DWORD cbOriginalValue;
  570. BYTE cbBuffer[QUERYBUFFERSIZE];
  571. LPBYTE lpByte = NULL;
  572. BOOL fAllocated = FALSE;
  573. GETARGPTR(pFrame, sizeof(REGQUERYVALUE16), parg16);
  574. GETOPTPTR(parg16->f2, 0, psz2);
  575. GETOPTPTR(parg16->f3, 0, lpszData);
  576. GETOPTPTR(parg16->f4, 0, lpcbValue);
  577. if ( lpcbValue == NULL ) { // Prevent us from dying just in case!
  578. FREEOPTPTR(psz2);
  579. FREEOPTPTR(lpszData);
  580. FREEOPTPTR(lpcbValue);
  581. FREEARGPTR(parg16);
  582. return( WIN16_ERROR_INVALID_PARAMETER );
  583. }
  584. cbOriginalValue = cbValue = FETCHDWORD(*lpcbValue);
  585. #ifdef FE_SB // for Lotus 123 by v-kenich 94.Aug.27
  586. // Lotus doesn't set value to *lpcb in one case
  587. // in other case set 80
  588. // so when not set, assume 80 and set 80 in this field
  589. if (CURRENTPTD()->dwWOWCompatFlagsFE & WOWCF_FE_FORCEREGQRYLEN) {
  590. if (cbValue > 80) {
  591. cbOriginalValue = cbValue = 80;
  592. }
  593. }
  594. #endif // FE_SB
  595. // Fix MSTOOLBR.DLL unintialized cbValue by forcing it to be less than 64K
  596. // Win 3.1 Registry values are always less than 64K.
  597. cbOriginalValue &= 0x0000FFFF;
  598. if ( lpszData == NULL ) {
  599. lpByte = NULL;
  600. } else {
  601. lpByte = cbBuffer;
  602. if ( cbOriginalValue > QUERYBUFFERSIZE ) {
  603. lpByte = malloc_w(cbOriginalValue);
  604. if ( lpByte == NULL ) {
  605. FREEOPTPTR(psz2);
  606. FREEOPTPTR(lpszData);
  607. FREEOPTPTR(lpcbValue);
  608. FREEARGPTR(parg16);
  609. RETURN( WIN16_ERROR_OUTOFMEMORY );
  610. }
  611. fAllocated = TRUE;
  612. }
  613. }
  614. hkey = (HKEY)FETCHDWORD(parg16->f1);
  615. if ((DWORD)hkey == WIN16_HKEY_CLASSES_ROOT) {
  616. hkey = (HKEY)HKEY_CLASSES_ROOT;
  617. }
  618. if (!hkey) {
  619. if (psz2) {
  620. psz1 = Remove_Classes (psz2);
  621. }
  622. hkey = HKEY_CLASSES_ROOT;
  623. } else {
  624. psz1 = psz2;
  625. }
  626. ul = DPM_RegQueryValue (
  627. hkey,
  628. psz1,
  629. lpByte,
  630. &cbValue
  631. );
  632. if (ul == ERROR_SUCCESS) {
  633. if ( lpszData ) {
  634. memcpy( lpszData, lpByte, cbValue );
  635. }
  636. } else {
  637. if ( ul == ERROR_MORE_DATA ) {
  638. //
  639. // We need to allocate more
  640. //
  641. if ( fAllocated ) {
  642. free_w( lpByte );
  643. }
  644. lpByte = malloc_w( cbValue );
  645. if ( lpByte == NULL ) {
  646. if ((psz1) && (psz1 != psz2)) {
  647. // If we did some key name copying, then free that buffer
  648. free_w (psz1);
  649. }
  650. FREEOPTPTR(psz2);
  651. FREEOPTPTR(lpszData);
  652. FREEOPTPTR(lpcbValue);
  653. FREEARGPTR(parg16);
  654. RETURN(WIN16_ERROR_OUTOFMEMORY);
  655. }
  656. fAllocated = TRUE;
  657. ul = DPM_RegQueryValue( hkey,
  658. psz1,
  659. lpByte,
  660. &cbValue );
  661. cbValue = cbOriginalValue;
  662. if ( lpszData ) {
  663. memcpy( lpszData, lpByte, cbValue );
  664. }
  665. }
  666. }
  667. if ((psz1) && (psz1 != psz2)) {
  668. // If we did some key name copying, then free that buffer
  669. free_w (psz1);
  670. }
  671. if ( fAllocated ) {
  672. // If we've allocated memory for the output buffer, then free it
  673. free_w (lpByte);
  674. }
  675. STOREDWORD(*lpcbValue, cbValue);
  676. FLUSHVDMPTR(parg16->f4, 4, lpcbValue);
  677. if ( lpszData != NULL ) {
  678. FLUSHVDMPTR(parg16->f3, (USHORT)cbValue, lpszData);
  679. }
  680. ul = ConvertToWin31Error(ul);
  681. FREEOPTPTR(psz2);
  682. FREEOPTPTR(lpszData);
  683. FREEOPTPTR(lpcbValue);
  684. FREEARGPTR(parg16);
  685. RETURN(ul);
  686. }
  687. // This is a Win 9x API. It doesn't need some of the thunking required by
  688. // the Win 3.1 Regxxx() API's. ie. WIN16_HKEY_CLASSES_ROOT conversion &
  689. // ConvertToWin31Error().
  690. // Since this was brought over from the interpreted thunk code, it doesn't
  691. // require any special thunking for any of the parameters until an issue is
  692. // identified -- at which time this comment should be removed.
  693. ULONG FASTCALL WS32RegQueryValueEx(PVDMFRAME pFrame)
  694. {
  695. ULONG ul;
  696. register PREGQUERYVALUEEX3216 parg16;
  697. HKEY hkey;
  698. PSZ lpszValueName;
  699. LPBYTE lpData;
  700. LPDWORD lpReserved, lpType, lpcbData;
  701. GETARGPTR(pFrame, sizeof(REGQUERYVALUE3216), parg16);
  702. hkey = (HKEY)FETCHDWORD(parg16->hKey);
  703. GETOPTPTR(parg16->lpszValue, 0, lpszValueName);
  704. GETOPTPTR(parg16->vpdwReserved, sizeof(DWORD), lpReserved);
  705. GETOPTPTR(parg16->vpdwType, sizeof(DWORD), lpType);
  706. GETOPTPTR(parg16->cbBuffer, sizeof(DWORD), lpcbData);
  707. GETOPTPTR(parg16->lpBuffer, *lpcbData, lpData);
  708. ul = DPM_RegQueryValueEx (hkey,
  709. lpszValueName,
  710. lpReserved,
  711. lpType,
  712. lpData,
  713. lpcbData);
  714. FREEOPTPTR(lpszValueName);
  715. FREEOPTPTR(lpReserved);
  716. FREEOPTPTR(lpType);
  717. FREEOPTPTR(lpData);
  718. FREEOPTPTR(lpcbData);
  719. FREEARGPTR(parg16);
  720. RETURN(ul);
  721. }
  722. ULONG FASTCALL WS32RegEnumKey(PVDMFRAME pFrame)
  723. {
  724. ULONG ul;
  725. register PREGENUMKEY16 parg16;
  726. HKEY hkey;
  727. LPBYTE lpszName;
  728. GETARGPTR(pFrame, sizeof(REGENUMKEY16), parg16);
  729. GETOPTPTR(parg16->f3, parg16->f4, lpszName);
  730. hkey = (HKEY)FETCHDWORD(parg16->f1);
  731. if ((DWORD)hkey == WIN16_HKEY_CLASSES_ROOT) {
  732. hkey = (HKEY)HKEY_CLASSES_ROOT;
  733. }
  734. ul = DPM_RegEnumKey (
  735. hkey,
  736. parg16->f2,
  737. lpszName,
  738. parg16->f4
  739. );
  740. FLUSHVDMPTR(parg16->f3, (USHORT)parg16->f4, lpszName);
  741. ul = ConvertToWin31Error(ul);
  742. FREEOPTPTR(lpszName);
  743. FREEARGPTR(parg16);
  744. RETURN(ul);
  745. }
  746. // This is a Win 9x API. It doesn't need some of the thunking required by
  747. // the Win 3.1 Regxxx() API's. ie. WIN16_HKEY_CLASSES_ROOT conversion &
  748. // ConvertToWin31Error().
  749. // Since this was brought over from the interpreted thunk code, it doesn't
  750. // require any special thunking for any of the parameters until an issue is
  751. // identified -- at which time this comment should be removed.
  752. ULONG FASTCALL WS32RegEnumValue(PVDMFRAME pFrame)
  753. {
  754. ULONG ul;
  755. register PREGENUMVALUE3216 parg16;
  756. HKEY hkey;
  757. PSZ lpszValueName;
  758. LPBYTE lpData;
  759. LPDWORD lpcbValueName, lpReserved, lpType, lpcbData;
  760. GETARGPTR(pFrame, sizeof(REGENUMVALUE3216), parg16);
  761. hkey = (HKEY)FETCHDWORD(parg16->hKey);
  762. GETOPTPTR(parg16->lpcchValue, sizeof(DWORD), lpcbValueName);
  763. GETOPTPTR(parg16->lpszValue, *lpcbValueName, lpszValueName);
  764. GETOPTPTR(parg16->lpdwReserved, sizeof(DWORD), lpReserved);
  765. GETOPTPTR(parg16->lpdwType, sizeof(DWORD), lpType);
  766. GETOPTPTR(parg16->lpcbData, sizeof(DWORD), lpcbData);
  767. GETOPTPTR(parg16->lpbData, *lpcbData, lpData);
  768. ul = DPM_RegEnumValue (hkey,
  769. parg16->iValue,
  770. lpszValueName,
  771. lpcbValueName,
  772. lpReserved,
  773. lpType,
  774. lpData,
  775. lpcbData);
  776. FREEOPTPTR(lpszValueName);
  777. FREEOPTPTR(lpcbValueName);
  778. FREEOPTPTR(lpReserved);
  779. FREEOPTPTR(lpType);
  780. FREEOPTPTR(lpData);
  781. FREEOPTPTR(lpcbData);
  782. FREEARGPTR(parg16);
  783. RETURN(ul);
  784. }
  785. ULONG FASTCALL WS32DragAcceptFiles(PVDMFRAME pFrame)
  786. {
  787. ULONG ul=0;
  788. register PDRAGACCEPTFILES16 parg16;
  789. GETARGPTR(pFrame, sizeof(DRAGACCEPTFILES16), parg16);
  790. DragAcceptFiles(HWND32(parg16->f1),(BOOL)parg16->f2);
  791. FREEARGPTR(parg16);
  792. RETURN(ul);
  793. }
  794. ULONG FASTCALL WS32DragQueryFile(PVDMFRAME pFrame)
  795. {
  796. ULONG ul = 0l;
  797. register PDRAGQUERYFILE16 parg16;
  798. LPSTR lpFile;
  799. HANDLE hdfs32;
  800. GETARGPTR(pFrame, sizeof(DRAGQUERYFILE16), parg16);
  801. if (hdfs32 = HDROP32(parg16->f1)) {
  802. GETOPTPTR(parg16->f3, parg16->f4, lpFile);
  803. ul = DragQueryFileAorW (hdfs32, INT32(parg16->f2),
  804. lpFile, parg16->f4, TRUE,TRUE);
  805. if ((lpFile != NULL) && (parg16->f2 != -1)) {
  806. FLUSHVDMPTR(parg16->f3, parg16->f4, lpFile);
  807. }
  808. FREEOPTPTR(lpFile);
  809. }
  810. FREEARGPTR(parg16);
  811. RETURN(ul);
  812. }
  813. ULONG FASTCALL WS32DragFinish(PVDMFRAME pFrame)
  814. {
  815. register PDRAGFINISH16 parg16;
  816. HDROP h32;
  817. GETARGPTR(pFrame, sizeof(PDRAGFINISH16), parg16);
  818. //
  819. // freehdrop16, frees the alias and returns the corresponding h32
  820. //
  821. if (h32 = FREEHDROP16(parg16->f1)) {
  822. DragFinish(h32);
  823. }
  824. FREEARGPTR(parg16);
  825. return 0;
  826. }
  827. ULONG FASTCALL WS32ShellAbout (PVDMFRAME pFrame)
  828. {
  829. ULONG ul;
  830. register PSHELLABOUT16 parg16;
  831. PSZ psz2;
  832. PSZ psz3;
  833. GETARGPTR(pFrame, sizeof(SHELLABOUT16), parg16);
  834. GETPSZPTR(parg16->f2, psz2);
  835. GETPSZPTR(parg16->f3, psz3);
  836. ul = GETINT16(ShellAbout (
  837. HWND32(parg16->f1),
  838. psz2,
  839. psz3,
  840. HICON32(parg16->f4)
  841. ));
  842. FREEPSZPTR(psz2);
  843. FREEPSZPTR(psz3);
  844. FREEARGPTR(parg16);
  845. RETURN(ul);
  846. }
  847. // NOTE : The return value can be instance handle or the handle of a
  848. // DDE server. So, take this information into account while debugging
  849. // the effect of the return value from this API. ChandanC 4/24/92.
  850. // You would notice that I am treating the return value as HINSTANCE.
  851. //
  852. ULONG FASTCALL WS32ShellExecute (PVDMFRAME pFrame)
  853. {
  854. ULONG ul;
  855. register PSHELLEXECUTE16 parg16;
  856. PSZ psz2;
  857. PSZ psz3;
  858. PSZ psz4;
  859. PSZ psz5;
  860. GETARGPTR(pFrame, sizeof(SHELLEXECUTE16), parg16);
  861. GETPSZPTR(parg16->f2, psz2);
  862. GETPSZPTR(parg16->f3, psz3);
  863. GETPSZPTR(parg16->f4, psz4);
  864. GETPSZPTR(parg16->f5, psz5);
  865. UpdateDosCurrentDirectory( DIR_DOS_TO_NT);
  866. ul = GETHINST16(WOWShellExecute (
  867. HWND32(parg16->f1),
  868. psz2,
  869. psz3,
  870. psz4,
  871. psz5,
  872. parg16->f6,
  873. (LPVOID) W32ShellExecuteCallBack
  874. ));
  875. FREEPSZPTR(psz2);
  876. FREEPSZPTR(psz3);
  877. FREEPSZPTR(psz4);
  878. FREEPSZPTR(psz5);
  879. FREEARGPTR(parg16);
  880. RETURN(ul);
  881. }
  882. /*
  883. * This is an equivalent of a nasty win'95 style hack that prevents us from
  884. * launching things from winexec that are lfn-based
  885. * Unfortunate as it is -- this alone can't save us in all the cases -- it
  886. * just allows for a fix to ole-based method (another method should be
  887. * employed to fix winexec)
  888. *
  889. * The code was stolen from base/client/process.c
  890. * with win95's method being to try CreateProcess instead of SearchPath within
  891. * the inner loop.
  892. *
  893. * Parameters:
  894. * lpstrParsed -- destination string which upon successful return will contain
  895. * 1. Short path for an exe file
  896. * 2. The rest of the cmdline in an appropriate order
  897. * lpszCmdLine -- command line for an app with parameters
  898. * cchParsed -- character count for the lpstrParsed string
  899. *
  900. * fConvert -- if TRUE, path is going to be converted to its short
  901. * form, if FALSE -- it is going to be quoted for winexec
  902. * not to stumble upon it.
  903. *
  904. */
  905. ULONG WS32ParseCmdLine(
  906. PBYTE lpstrParsed,
  907. LPSZ lpszCmdLine,
  908. ULONG cchstrParsed,
  909. BOOL fConvert)
  910. {
  911. int cb = 0;
  912. BOOL fQuote = FALSE; // was there a quote ?
  913. PCHAR psz = lpszCmdLine; // original ptr to the command line
  914. CHAR szFileName[MAX_PATH];// exe filename in its final form (from szCmd)
  915. CHAR szCmd[MAX_PATH]; // command that is being built from lpszCmdLine
  916. PCHAR pszCmd = szCmd;
  917. CHAR c;
  918. DWORD dwLength, dwLengthFileName, dwLengthCmdTail;
  919. DWORD dwError = ERROR_SUCCESS;
  920. WOW32ASSERTMSGF(lstrlen(lpszCmdLine) < sizeof(szCmd)/sizeof(szCmd[0]),
  921. ("WOW::WS32ParseCmdLine -- cmd line too long\n"));
  922. c = *psz;
  923. while(TRUE) {
  924. if ('\"' == c) {
  925. fQuote = !fQuote; // state variable -- flip quoting
  926. }
  927. else {
  928. // now check for space chars
  929. // the condition here is: if it is outside of a quote -- then
  930. // space is a delimiter. Another condition is an end of a string
  931. if (((' ' == c || '\t' == c) && !fQuote) || ('\0' == c)) {
  932. // delimiter -- now try for a file search
  933. *pszCmd = '\0';
  934. dwLengthFileName = DPM_SearchPath(NULL,
  935. szCmd,
  936. ".exe",
  937. sizeof(szFileName)/sizeof(szFileName[0]),
  938. szFileName,
  939. NULL);
  940. // return value is length in chars
  941. if (!dwLengthFileName || dwLengthFileName > sizeof(szFileName)/sizeof(szFileName[0])) {
  942. // oops -- we have found none
  943. // so remember the error
  944. dwError = ERROR_FILE_NOT_FOUND;
  945. if ('\0' == c) {
  946. break; // end of the string
  947. }
  948. }
  949. else {
  950. // szFileName is what we need
  951. dwError = ERROR_SUCCESS;
  952. break;
  953. }
  954. }
  955. *pszCmd++ = c; // copy the character over and continue
  956. cb++;
  957. if(cb > sizeof(szCmd)/sizeof(szCmd[0])) {
  958. dwError = ERROR_INSUFFICIENT_BUFFER;
  959. break;
  960. }
  961. }
  962. // now move to the next char
  963. c = *++psz;
  964. }
  965. if (ERROR_SUCCESS != dwError) {
  966. return(dwError);
  967. }
  968. dwLengthCmdTail = strlen(psz);
  969. // now
  970. // psz points to a delimiter char that we have terminated our search on.
  971. // the part before this char -- is exe filename
  972. // the part after this char -- cmdline tail
  973. if (fConvert) {
  974. // now we go converting first
  975. dwLength = DPM_GetShortPathName(szFileName, lpstrParsed, cchstrParsed);
  976. if (!dwLength || dwLength > cchstrParsed-1) {
  977. LOGDEBUG(0, ("WS32ParseCmdLine: Can't convert to the short name\n"));
  978. WOW32ASSERT(FALSE);
  979. return(GetLastError());
  980. }
  981. if (dwLength + dwLengthCmdTail > cchstrParsed - 1) {
  982. LOGDEBUG(0, ("WS32ParseCmdLine: Buffer too short for cmdline tail\n"));
  983. WOW32ASSERT(FALSE);
  984. return(ERROR_INSUFFICIENT_BUFFER);
  985. }
  986. }
  987. else {
  988. // now here we just insert quotes around the filename -- unless there
  989. // already were some quotes surrounding it
  990. if (dwLengthFileName + 2 > cchstrParsed - 1) {
  991. LOGDEBUG(0, ("WS32ParseCmdLine: Buffer too short for quoted filename\n"));
  992. WOW32ASSERT(FALSE);
  993. return(ERROR_INSUFFICIENT_BUFFER);
  994. }
  995. *lpstrParsed++ = '\"';
  996. lstrcpyn(lpstrParsed, szFileName, dwLengthFileName+1);
  997. lstrcat(lpstrParsed, "\"");
  998. }
  999. lstrcat(lpstrParsed, psz);
  1000. return(ERROR_SUCCESS);
  1001. }
  1002. extern DWORD demSetCurrentDirectoryGetDrive(LPSTR lpDirectoryName, PUINT pDriveNum);
  1003. extern DWORD demLFNGetCurrentDirectory(UINT DriveNum, LPSTR lpDirectoryName);
  1004. WORD W32ShellExecuteCallBack (LPSZ lpszCmdLine, WORD fuCmdShow, LPSZ lpszNewDir)
  1005. {
  1006. PBYTE lpstr16;
  1007. PARM16 Parm16;
  1008. ULONG ul = 0;
  1009. VPVOID vpstr16;
  1010. CHAR szCurrentDirectory[MAX_PATH];
  1011. UINT Drive;
  1012. DWORD dwStatus;
  1013. BOOL fRestoreDir;
  1014. // what +5 is doing here ? The reasoning is like this :
  1015. // generated short path could never be longer than the original (long path)
  1016. //
  1017. ULONG cchstr16 = lstrlen(lpszCmdLine) + 5;
  1018. UpdateDosCurrentDirectory(DIR_NT_TO_DOS);
  1019. // we're given a current directory here --
  1020. // so we see if this matches our current directory
  1021. // demSetCurrentDirectoryLong(
  1022. dwStatus = demLFNGetCurrentDirectory(0, szCurrentDirectory);
  1023. fRestoreDir = NT_SUCCESS(dwStatus);
  1024. dwStatus = demSetCurrentDirectoryGetDrive(lpszNewDir, &Drive);
  1025. if (NT_SUCCESS(dwStatus)) {
  1026. DosWowSetDefaultDrive((UCHAR)Drive);
  1027. }
  1028. if (vpstr16 = malloc16 (cchstr16)) { // .exe, remember ?
  1029. GETMISCPTR (vpstr16, lpstr16);
  1030. if (lpstr16) {
  1031. // we cannot simply copy the command line here -- although memory
  1032. // that was allocated is going to be sufficient.
  1033. // Problem is that winexec will choke when the program name
  1034. // is denoted as Long File Name -- which is the case with new Office
  1035. // applications. The rule should be -- whatever comes into land16
  1036. // should be in a form of a short file name.
  1037. // mind you that vpstr16 is big enough for both the long and
  1038. // short name -- so this code requires no memory realloc
  1039. // now we need to have
  1040. ul = WS32ParseCmdLine(lpstr16, lpszCmdLine, cchstr16, TRUE);
  1041. if (ERROR_SUCCESS != ul) {
  1042. WOW32ASSERTMSGF(FALSE, ("WS32ParseCmdLine failed: 0x%lx\n", ul));
  1043. lstrcpy (lpstr16, lpszCmdLine);
  1044. }
  1045. Parm16.WndProc.wParam = fuCmdShow;
  1046. Parm16.WndProc.lParam = vpstr16;
  1047. CallBack16(RET_WINEXEC, &Parm16, 0, &ul);
  1048. FREEMISCPTR (lpstr16);
  1049. }
  1050. free16(vpstr16);
  1051. }
  1052. if (fRestoreDir) {
  1053. dwStatus = demSetCurrentDirectoryGetDrive(szCurrentDirectory, &Drive);
  1054. if (NT_SUCCESS(dwStatus)) {
  1055. DosWowSetDefaultDrive((UCHAR)Drive);
  1056. }
  1057. }
  1058. return (LOWORD(ul));
  1059. }
  1060. ULONG FASTCALL WS32FindExecutable (PVDMFRAME pFrame)
  1061. {
  1062. ULONG ul;
  1063. register PFINDEXECUTABLE16 parg16;
  1064. PSZ psz1;
  1065. PSZ psz2;
  1066. PSZ psz3;
  1067. GETARGPTR(pFrame, sizeof(FINDEXECUTABLE16), parg16);
  1068. GETPSZPTR(parg16->f1, psz1);
  1069. GETPSZPTR(parg16->f2, psz2);
  1070. GETPSZPTRNOLOG(parg16->f3, psz3);
  1071. ul = (ULONG) FindExecutable (
  1072. psz1,
  1073. psz2,
  1074. psz3
  1075. );
  1076. LOGDEBUG(11,(" returns @%08lx: \"%.80s\"\n", FETCHDWORD(parg16->f3), psz3));
  1077. FLUSHVDMPTR(parg16->f3, strlen(psz3)+1, psz3);
  1078. // This is for success condition.
  1079. if (ul > 32) {
  1080. ul = GETHINST16 (ul);
  1081. }
  1082. FREEPSZPTR(psz1);
  1083. FREEPSZPTR(psz2);
  1084. FREEPSZPTR(psz3);
  1085. FREEARGPTR(parg16);
  1086. RETURN(ul);
  1087. }
  1088. ULONG FASTCALL WS32ExtractIcon (PVDMFRAME pFrame)
  1089. {
  1090. ULONG ul;
  1091. register PEXTRACTICON16 parg16;
  1092. PSZ psz;
  1093. UINT Id;
  1094. GETARGPTR(pFrame, sizeof(EXTRACTICON16), parg16);
  1095. GETPSZPTR(parg16->f2, psz);
  1096. Id = (parg16->f3 == (WORD)0xffff) ? (UINT)(SHORT)parg16->f3 :
  1097. (UINT)parg16->f3;
  1098. ul = (ULONG) ExtractIcon (HMODINST32(parg16->f1), psz, Id);
  1099. // This is for success condition.
  1100. if ((Id != (UINT)(-1)) && ul > 1) {
  1101. ul = GETHICON16(ul);
  1102. }
  1103. FREEPSZPTR(psz);
  1104. FREEARGPTR(parg16);
  1105. RETURN(ul);
  1106. }
  1107. //
  1108. // This routine convert the Win 32 registry error codes to Win 31
  1109. // error codes.
  1110. //
  1111. ULONG ConvertToWin31Error(ULONG ul)
  1112. {
  1113. LOGDEBUG(3, ("WOW::ConvertToWin31Error: Ret value from NT = %08lx\n", ul));
  1114. switch (ul) {
  1115. case ERROR_SUCCESS: return(WIN16_ERROR_SUCCESS);
  1116. case ERROR_BADDB: return(WIN16_ERROR_BADDB);
  1117. case ERROR_BADKEY: return(WIN16_ERROR_BADKEY);
  1118. case ERROR_CANTOPEN: return(WIN16_ERROR_CANTOPEN);
  1119. case ERROR_CANTREAD: return(WIN16_ERROR_CANTREAD);
  1120. case ERROR_CANTWRITE: return(WIN16_ERROR_CANTWRITE);
  1121. case ERROR_OUTOFMEMORY: return(WIN16_ERROR_OUTOFMEMORY);
  1122. case ERROR_INVALID_PARAMETER: return(WIN16_ERROR_INVALID_PARAMETER);
  1123. case ERROR_EA_ACCESS_DENIED: return(WIN16_ERROR_ACCESS_DENIED);
  1124. case ERROR_MORE_DATA: return(WIN16_ERROR_INVALID_PARAMETER);
  1125. case ERROR_FILE_NOT_FOUND: return(WIN16_ERROR_BADKEY);
  1126. case ERROR_NO_MORE_ITEMS: return(WIN16_ERROR_BADKEY);
  1127. default:
  1128. LOGDEBUG(3, ("WOW::Registry Error Code unknown =%08lx : returning 8 (WIN16_ERROR_ACCESS_DENIED)\n", ul));
  1129. return (WIN16_ERROR_ACCESS_DENIED);
  1130. }
  1131. }
  1132. LPSZ Remove_Classes (LPSZ psz)
  1133. {
  1134. LPSZ lpsz;
  1135. LPSZ lpsz1;
  1136. if (!WOW32_stricmp (".classes", psz)) {
  1137. if (lpsz = malloc_w (1)) {
  1138. *lpsz = '\0';
  1139. return (lpsz);
  1140. }
  1141. }
  1142. else {
  1143. if (*psz) {
  1144. lpsz = WOW32_strchr (psz, '\\');
  1145. if (lpsz) {
  1146. *lpsz = '\0';
  1147. if (!WOW32_stricmp (".classes", lpsz)) {
  1148. *lpsz = '\\';
  1149. if (lpsz1 = malloc_w (strlen(lpsz+1)+1)) {
  1150. strcpy (lpsz1, (lpsz+1));
  1151. return (lpsz1);
  1152. }
  1153. else {
  1154. return (0);
  1155. }
  1156. }
  1157. *lpsz = '\\';
  1158. return (psz);
  1159. }
  1160. else {
  1161. return (psz);
  1162. }
  1163. }
  1164. else {
  1165. return (psz);
  1166. }
  1167. }
  1168. return (psz);
  1169. }
  1170. //****************************************************************************
  1171. // DropFilesHandler -
  1172. // takes either h16 or h32 as input. flInput identifies the type of the
  1173. // handle and other operations to perform. return value varies but in most
  1174. // cases it is the opposite to the 'input type'- ie returns h16 if h32 was
  1175. // input and viceversa.
  1176. // - nanduri
  1177. //****************************************************************************
  1178. LPDROPALIAS glpDropAlias = NULL;
  1179. LPDROPALIAS DropFilesFind(DWORD h, UINT fInput, LPDROPALIAS* ppPrev)
  1180. {
  1181. LPDROPALIAS lpT = glpDropAlias;
  1182. LPDROPALIAS lpTPrev = NULL;
  1183. WOW32ASSERT(h);
  1184. WOW32ASSERT((!!(fInput & HDROP_H16)) ^ (!!(fInput & HDROP_H32)));
  1185. while (NULL != lpT) {
  1186. if (fInput & HDROP_H16) {
  1187. if ((lpT->h16 & ~1) == (((HAND16)h) & ~1)) {
  1188. break;
  1189. }
  1190. }
  1191. else if (fInput & HDROP_H32) {
  1192. if (lpT->h32 == (HANDLE)h) {
  1193. break;
  1194. }
  1195. }
  1196. lpTPrev = lpT;
  1197. lpT = lpT->lpNext;
  1198. }
  1199. if (ppPrev) {
  1200. *ppPrev = lpTPrev;
  1201. }
  1202. return(lpT);
  1203. }
  1204. DWORD DropFilesHandler(HAND16 h16, HANDLE h32, UINT flInput)
  1205. {
  1206. LPDROPALIAS lpT;
  1207. LPDROPALIAS lpTprev;
  1208. DWORD dwRet = 0;
  1209. // assert if specified both or neither handle or flag
  1210. WOW32ASSERT((h16) || (h32));
  1211. WOW32ASSERT((!!(flInput & HDROP_H32)) ^ (!!(flInput & HDROP_H16)));
  1212. // find handle
  1213. lpT = DropFilesFind(flInput & HDROP_H16 ? (DWORD)h16 : (DWORD)h32,
  1214. flInput,
  1215. &lpTprev);
  1216. //
  1217. // if not found, create the alias if requested
  1218. //
  1219. if (lpT == (LPDROPALIAS)NULL && (flInput & HDROP_ALLOCALIAS)) {
  1220. if (lpT = malloc_w(sizeof(DROPALIAS))) {
  1221. lpT->h16 = h16;
  1222. lpT->h32 = h32;
  1223. lpT->lpNext = glpDropAlias;
  1224. lpT->dwFlags = 0;
  1225. glpDropAlias = lpT;
  1226. flInput |= HDROP_COPYDATA;
  1227. }
  1228. }
  1229. //
  1230. // if found - do the necessary operation. all (other) HDROP_* flags
  1231. // have priority over HDROP_H16 and HDROP_H32 flags.
  1232. //
  1233. if (lpT) {
  1234. if (flInput & HDROP_COPYDATA) {
  1235. if (h32) {
  1236. dwRet = (DWORD) (lpT->h16 = CopyDropFilesFrom32(h32));
  1237. lpT->dwFlags |= ALLOC_H16;
  1238. } else {
  1239. dwRet = (DWORD) (lpT->h32 = CopyDropFilesFrom16(h16));
  1240. lpT->dwFlags |= ALLOC_H32;
  1241. }
  1242. }
  1243. else if (flInput & HDROP_FREEALIAS) {
  1244. dwRet = (DWORD)lpT->h32;
  1245. if (lpTprev) {
  1246. lpTprev->lpNext = lpT->lpNext;
  1247. }
  1248. else {
  1249. glpDropAlias = lpT->lpNext;
  1250. }
  1251. free_w(lpT);
  1252. }
  1253. else if (flInput & HDROP_H16) {
  1254. dwRet = (DWORD)lpT->h32;
  1255. }
  1256. else if (flInput & HDROP_H32) {
  1257. dwRet = (DWORD)lpT->h16;
  1258. }
  1259. }
  1260. return (dwRet);
  1261. }
  1262. //
  1263. // FindAndReleaseHDrop16
  1264. // Called from the 16-bit GlobalFree to see if we need to free alias
  1265. // associated with this handle
  1266. // The actual call is made through the wowddeglobalfree
  1267. // Function frees 32-bit handle (or disposes of it using DragFinish
  1268. // for consistency) but 16-bit handle is freed elsewere
  1269. //
  1270. BOOL FindAndReleaseHDrop16 (HAND16 h16)
  1271. {
  1272. LPDROPALIAS lpT;
  1273. LPDROPALIAS lpTPrev;
  1274. if (NULL != (lpT = DropFilesFind(h16, HDROP_H16, &lpTPrev))) {
  1275. // found, now free 32-bit handle, but not 16-bit one
  1276. // this assert will fire if we had not allocated 32-bit handle but
  1277. // app tried to free the 16-bit equivalent instead
  1278. LOGDEBUG(LOG_ALWAYS, ("HDrop16: removing handle 16:%lx 32:%lx\n",
  1279. (DWORD)h16,
  1280. (DWORD)lpT->h32));
  1281. if (lpT->dwFlags & ALLOC_H32) {
  1282. LOGDEBUG(LOG_ALWAYS, ("HDROP16: h32 allocated through OLE\n"));
  1283. WOWGLOBALFREE((HANDLE)lpT->h32);
  1284. }
  1285. else { // this handle was not allocated - but rather retrieved via old
  1286. // style dropfiles mechanism
  1287. LOGDEBUG(LOG_ALWAYS, ("HDrop16: h32 retrieved from shell\n"));
  1288. DragFinish((HDROP)lpT->h32);
  1289. }
  1290. // now unlink
  1291. if (NULL != lpTPrev) {
  1292. lpTPrev->lpNext = lpT->lpNext;
  1293. }
  1294. else {
  1295. glpDropAlias = lpT->lpNext;
  1296. }
  1297. // unmark 16-bit memory as being dde...
  1298. W32UnMarkDDEHandle(h16);
  1299. // free the list item
  1300. free_w(lpT);
  1301. }
  1302. return(NULL != lpT);
  1303. }
  1304. //****************************************************************************
  1305. // CopyDropFilesStruct -
  1306. //
  1307. // returns h16.
  1308. //****************************************************************************
  1309. HAND16 CopyDropFilesFrom32(HANDLE h32)
  1310. {
  1311. UINT cbSize;
  1312. HAND16 hRet = 0;
  1313. HAND16 hMem;
  1314. VPVOID vp;
  1315. //
  1316. // the allocated 16bit handle and the corresponding 32bit handle
  1317. // are freed in the shell api 'DragFinish' (if it is called by the app)
  1318. //
  1319. cbSize = GlobalSize((HANDLE)h32);
  1320. if (vp = GlobalAllocLock16(GMEM_DDESHARE, cbSize, &hMem)) {
  1321. LPDROPFILESTRUCT lpdfs32;
  1322. PDROPFILESTRUCT16 lpdfs16;
  1323. ULONG uIgnore;
  1324. GETMISCPTR(vp, lpdfs16);
  1325. if (lpdfs32 = (LPDROPFILESTRUCT)GlobalLock((HANDLE)h32)) {
  1326. //
  1327. // pFiles is a byte count to the beginning of the file.
  1328. //
  1329. lpdfs16->pFiles = sizeof(DROPFILESTRUCT16);
  1330. lpdfs16->x = (SHORT) lpdfs32->pt.x;
  1331. lpdfs16->y = (SHORT) lpdfs32->pt.y;
  1332. lpdfs16->fNC = (SHORT) lpdfs32->fNC;
  1333. if (lpdfs32->fWide) {
  1334. RtlUnicodeToMultiByteN(((PCHAR)lpdfs16)+lpdfs16->pFiles,
  1335. cbSize-lpdfs16->pFiles,
  1336. &uIgnore,
  1337. (PWSTR)(((PCHAR)lpdfs32)+lpdfs32->pFiles),
  1338. cbSize-lpdfs32->pFiles);
  1339. }
  1340. else {
  1341. //
  1342. // Copy the files after each structure.
  1343. // The offset from the beginning of the structure changes
  1344. // (since the structures are differenly sized), but we
  1345. // compensate by changes pFiles above.
  1346. //
  1347. RtlCopyMemory(lpdfs16+1, lpdfs32+1,
  1348. GlobalSize((HANDLE)h32) - sizeof(DROPFILESTRUCT));
  1349. }
  1350. GlobalUnlock((HANDLE)h32);
  1351. hRet = hMem;
  1352. // and before we return - mark this memory as being suspect for
  1353. // stray mapping release
  1354. // This function in wdde.c marks arena with GAH_PHANTOM flag
  1355. // we will destroy the alias when the globalfree is called either
  1356. // from 16-bit shell api DragFinish or from 16-bit ReleaseStgMedium
  1357. W32MarkDDEHandle(hMem);
  1358. }
  1359. else {
  1360. GlobalUnlockFree16(vp);
  1361. }
  1362. FREEMISCPTR(lpdfs16);
  1363. }
  1364. return (hRet);
  1365. }
  1366. /*--------------------------------------------------------------------------*/
  1367. /* */
  1368. /* CopyDropFilesFrom16() */
  1369. /* */
  1370. /*--------------------------------------------------------------------------*/
  1371. HANDLE CopyDropFilesFrom16(HAND16 h16)
  1372. {
  1373. HANDLE h32 = 0;
  1374. ULONG cbSize16;
  1375. UINT cbSize32;
  1376. VPVOID vp;
  1377. if (vp = GlobalLock16(h16, &cbSize16)) {
  1378. LPDROPFILESTRUCT lpdfs32;
  1379. PDROPFILESTRUCT16 lpdfs16;
  1380. GETMISCPTR(vp, lpdfs16);
  1381. cbSize32 = 2*sizeof(TCHAR) + sizeof(DROPFILESTRUCT) +
  1382. (cbSize16 - sizeof(DROPFILESTRUCT16));
  1383. if (h32 = WOWGLOBALALLOC(GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
  1384. cbSize32)){
  1385. lpdfs32 = (LPDROPFILESTRUCT)GlobalLock(h32);
  1386. lpdfs32->pFiles = sizeof(DROPFILESTRUCT);
  1387. lpdfs32->pt.x = (LONG) lpdfs16->x;
  1388. lpdfs32->pt.y = (LONG) lpdfs16->y;
  1389. lpdfs32->fNC = lpdfs16->fNC;
  1390. lpdfs32->fWide = FALSE;
  1391. RtlCopyMemory(lpdfs32+1, lpdfs16+1,
  1392. cbSize16 - sizeof(DROPFILESTRUCT16));
  1393. GlobalUnlock(h32);
  1394. }
  1395. FREEMISCPTR(lpdfs16);
  1396. GlobalUnlock16(h16);
  1397. }
  1398. return(h32);
  1399. }