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.

1731 lines
52 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WKERNEL.C
  8. * WOW32 16-bit Kernel API support
  9. *
  10. * History:
  11. * Created 07-Mar-1991 by Jeff Parsons (jeffpar)
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. MODNAME(wkernel.c);
  16. int W31_w9x_MyStrLen(LPSTR lpstr);
  17. /*******************************************************************************
  18. // Hack action & attribute flags to use with WOWCF2_HACKPROFILECALL.
  19. // See how these are used with the parameters for ProfileHacks()
  20. *******************************************************************************/
  21. #define HPC_INTFUNCTION 0x00000001
  22. #define HPC_STRFUNCTION 0x00000002
  23. #define HPC_USEDEFAULT 0x00001000
  24. #define HPC_RETURNHACKVALUE 0x00002000
  25. #define HPC_UPPERCASE 0x00004000
  26. #define HPC_LOWERCASE 0x00008000
  27. #define HPC_HASENVIRONMENTVAR 0x00000100
  28. #define HPC_CONVERTTOSHORTPATH 0x00000200
  29. #define HPC_MULTIKEY 0x00000400
  30. /*******************************************************************************
  31. HPC_MULTIKEY Specifies that the hack applies to several Keys in a
  32. seciton in the .ini file. Each key name should be
  33. separated by a pipe ('|') char. ie. Key1|Key2|Key3.
  34. HPC_INTFUNCTION Specifies this is a xxxxProfileInt() type function.
  35. Causes pDefault & pRetBuf to be interpreted as PINT.
  36. HPC_STRFUNCTION Specifies this is a xxxxProfileString() type function.
  37. Causes pDefault & pRetBuf to be interpreted as LPSTR.
  38. The length of pRetBuf is specified by cbRetBuf.
  39. HPC_SECTIONFUNCTION Specifies this is a xxxxProfileSection() type function.
  40. (Not implemented) Causes pDefault & pRetBuf to be interpreted as PVOID
  41. buffer. The length of pRetBuf is specified by cbRetBuf.
  42. HPC_STRUCTFUNCTION Specifies this is a xxxxProfileStruct() type function.
  43. (Not implemented) Causes pDefault & pRetBuf to be interpreted as PVOID
  44. buffer. The length of pRetBuf is specified by cbRetBuf.
  45. HPC_USEDEFAULT Copy pDefault to pRetBuf for GetxxProfilexx() type API's.
  46. pDefault will be interpreted according to the
  47. HPC_xxxFUNCTION flags.
  48. HPC_RETURNHACKVALUE Used to specify that NewData should be copied to pRetBuf.
  49. The HPC_xxxxFUNCTION flags will determine how (data type)
  50. HPC_UPPERCASE Converts string(s) in pRetBuf to upper/lowercase. If
  51. HPC_LOWERCASE HPC_STRFUNCTION is set, the first string in pRetBuf is
  52. converted (to ther first NULL char). If the
  53. HPC_SECTIONFUNCTION flag is set, all strings in pRetBuf
  54. will be converted (Stops when the double-NULL char
  55. list-terminator is encountered).
  56. HPC_HASENVIRONMENTVAR The Xml string has an environment var of the form
  57. %VarName%.
  58. HPC_CONVERTTOSHORTPATH Converts the return string value to a short path.
  59. *******************************************************************************/
  60. // Treat as a unicode function.
  61. #define HPC_UNICODE 0x80000000
  62. // Used to specify which API you want the hack for.
  63. // OR '|' in HPC_UNICODE for the Wide API's.
  64. #define HPC_GETPROFILEINT 0x40000000
  65. #define HPC_GETPRIVATEPROFILEINT 0x20000000
  66. #define HPC_GETPROFILESTRING 0x10000000
  67. #define HPC_GETPRIVATEPROFILESTRING 0x08000000
  68. #define HPC_GETPROFILESECTION 0x04000000
  69. #define HPC_GETPRIVATEPROFILESECTION 0x02000000
  70. #define HPC_GETPRIVATEPROFILESECTIONNAMES 0x01000000
  71. #define HPC_GETPRIVATEPROFILESTRUCT 0x00800000
  72. #define HPC_WRITEPROFILESTRING 0x00400000
  73. #define HPC_WRITEPRIVATEPROFILESTRING 0x00200000
  74. #define HPC_WRITEPROFILESECTION 0x00100000
  75. #define HPC_WRITEPRIVATEPROFILESECTION 0x00080000
  76. #define HPC_WRITEPRIVATEPROFILESTRUCT 0x00040000
  77. #define HPC_APIFLAGS (HPC_UNICODE | \
  78. HPC_GETPROFILEINT | \
  79. HPC_GETPRIVATEPROFILEINT | \
  80. HPC_GETPROFILESTRING | \
  81. HPC_GETPRIVATEPROFILESTRING | \
  82. HPC_GETPROFILESECTION | \
  83. HPC_GETPRIVATEPROFILESECTION | \
  84. HPC_GETPRIVATEPROFILESECTIONNAMES | \
  85. HPC_GETPRIVATEPROFILESTRUCT | \
  86. HPC_WRITEPROFILESTRING | \
  87. HPC_WRITEPRIVATEPROFILESTRING | \
  88. HPC_WRITEPROFILESECTION | \
  89. HPC_WRITEPRIVATEPROFILESECTION | \
  90. HPC_WRITEPRIVATEPROFILESTRUCT)
  91. #define HPC_ORD_FLAGS 0
  92. #define HPC_ORD_FILE 1
  93. #define HPC_ORD_SECTION 2
  94. #define HPC_ORD_KEY 3
  95. #define HPC_ORD_NEWDATA 4
  96. #define HPC_ORD_CBNEWDATA 5
  97. #define HPC_ORD_LAST (5+1) // if you change this you need to change all
  98. // the XML entries to reflect it
  99. DWORD pow16(int pow)
  100. {
  101. int i;
  102. DWORD dwPow = 1;
  103. for(i = 0; i < pow; i++)
  104. dwPow *= 0x10;
  105. return(dwPow);
  106. }
  107. char szDigits[] = "0123456789ABCDEF";
  108. // Convert a string of the form: "0x12345678" to its DWORD equivalent
  109. // Must have "0x" and have 8 digits or less.
  110. DWORD AsciiToHex(LPSTR pszHexString)
  111. {
  112. int i, len;
  113. int pow = 0;
  114. char c;
  115. DWORD dwVal;
  116. DWORD dwTot = 0;
  117. WOW32_strupr(pszHexString);
  118. WOW32ASSERTMSG((pszHexString[1] == 'X'),("WOW::AsciiToHex:Missing 'x'\n"));
  119. WOW32ASSERTMSG((strlen(pszHexString) == 10),("WOW::AsciiToHex:Bad len\n"));
  120. len = strlen(pszHexString)-1;
  121. // "0x" = 2, and 8 digits or less
  122. WOW32ASSERTMSG(((len > 2) && (len <= 10)),("WOW::AsciiToHex:Bad form\n"));
  123. // parse from the right back to the 'x'
  124. for(i = len; i > 1; i--) {
  125. c = pszHexString[i];
  126. for(dwVal = 0; dwVal < 0x10; dwVal++) {
  127. if(c == szDigits[dwVal]) {
  128. break;
  129. }
  130. }
  131. WOW32ASSERTMSG((dwVal < 0x10),("WOW::AsciiToHex:Bad hex char\n"));
  132. dwTot += dwVal * pow16(pow);
  133. pow++;
  134. }
  135. return(dwTot);
  136. }
  137. LPSTR *parsemulti(LPSTR pArgs, int *argc)
  138. {
  139. int i = 0;
  140. LPSTR *pArgv;
  141. *argc = 1;
  142. while(pArgs[i] != '\0') {
  143. if(pArgs[i++] == '|') {
  144. (*argc)++;
  145. }
  146. }
  147. if(*argc <= 1) {
  148. return(NULL);
  149. }
  150. pArgv = (LPSTR *)malloc_w(*argc * sizeof(LPSTR *));
  151. if(!pArgv) {
  152. return(NULL);
  153. }
  154. i = 1;
  155. pArgv[0] = pArgs;
  156. while(*pArgs) {
  157. if(*pArgs == '|') {
  158. *pArgs = '\0';
  159. pArgs++;
  160. pArgv[i++] = pArgs;
  161. }
  162. else {
  163. pArgs++;
  164. }
  165. }
  166. return(pArgv);
  167. }
  168. CHAR *CopyStrToBuf(LPSTR pszSrc, LPSTR pszDst, DWORD cbDst)
  169. {
  170. CHAR *pFinal = pszSrc;
  171. if(strlen(pszSrc) < cbDst) {
  172. strcpy(pszDst, pszSrc);
  173. WOW32_strlwr(pszDst); // lowercase for strstr() compares
  174. pFinal = pszDst;
  175. }
  176. return(pFinal);
  177. }
  178. /*
  179. Allows us to use the WOWCF2_HACKPROFILECALL comaptibility bit to fix a number
  180. of GetxxxProfilexxx() API calls by updating the app compat database rather
  181. than updating WOW32.DLL.
  182. The dbu.xml file should be of this format:
  183. <FLAG NAME="WOWCF2_HACKPROFILECALL" COMMAND_LINE="dwXmlFlags;FileName;SectionName;KeyName;NewData;cbNewData">/
  184. We can support multiple hack under the same flag just by repeating the same
  185. parameter list multiple times. You must preserve position by using the ';'
  186. delimeter for null arguments. Hence, to specify two HACKPROFILECALL hacks
  187. for the same app:
  188. <FLAG NAME="WOWCF2_HACKPROFILECALL" COMMAND_LINE="0x08002102;system.ini;mci;QTWVideo;%windir%\\system\\mciqtw.drv;0x00000000;0x20001001;sierra.ini;Config;VideoSpeed;;0x00000000"/>
  189. Note that in the above example, the second hack specification starts with the
  190. XML flags "0x20001001..."
  191. where:
  192. dwXmlFlags - hex string ("0x12345678") specifying HPC_xxx flags above.
  193. FileName - .ini file name. NULL if filename="win.ini"
  194. SectionName - [SectionName] from .ini file
  195. KeyName - aka "entry" value from .ini file.
  196. NewData1 - data to substitute for field specified in dwXmlFlags
  197. Data must be in
  198. cbNewData - number of bytes in newdata -- including all NULL chars
  199. If none of the hack specifications match, we return the passed in ul value
  200. which was returned by the original call to the 32-bit profile API.
  201. */
  202. ULONG ProfileHacks(DWORD dwFlags, LPCSTR pszFile, LPCSTR pszSection, LPCSTR pszKey, LPCSTR pDefault, INT iDefault, LPSTR pRetBuf, INT cbRetBuf, ULONG ul)
  203. {
  204. int i, cNumHacks;
  205. DWORD dwRet = 0;
  206. LPSTR *pArgv = NULL;
  207. DWORD dwXmlFlags;
  208. CHAR szBufApp[MAX_PATH], *pszBufApp;
  209. CHAR szBufHack[MAX_PATH], *pszBufHack;
  210. PFLAGINFOBITS pFlagInfoBits;
  211. pFlagInfoBits = CheckFlagInfo(WOWCOMPATFLAGS2, WOWCF2_HACKPROFILECALL);
  212. if(pFlagInfoBits) {
  213. pArgv = pFlagInfoBits->pFlagArgv;
  214. }
  215. if((NULL == pFlagInfoBits) || (NULL == pArgv)) {
  216. WOW32ASSERTMSG((FALSE), ("\nWOW::ProfileHacks:Must use command_line params with this compatibility flag!\n"));
  217. return(ul);
  218. }
  219. // Make sure the number of XML command line params are correct
  220. if(pFlagInfoBits->dwFlagArgc % HPC_ORD_LAST) {
  221. WOW32ASSERTMSG((FALSE), ("\nWOW::ProfileHacks:Incorrect number of args in XML database file!\n"));
  222. return(ul);
  223. }
  224. // Get the total number of profile hacks associated with this app
  225. cNumHacks = pFlagInfoBits->dwFlagArgc / HPC_ORD_LAST;
  226. // save the lowercase version of the passed in filename string....
  227. pszBufApp = CopyStrToBuf((CHAR *)pszFile,
  228. szBufApp,
  229. sizeof(szBufApp)/sizeof(CHAR));
  230. // loop through all the hacks
  231. for(i = 0; i < cNumHacks; i++) {
  232. // get the flags for this hack
  233. dwXmlFlags = AsciiToHex(pArgv[HPC_ORD_FLAGS]);
  234. // If this isn't the API we had in mind for this hack, check next hack
  235. // match...
  236. if(!((HPC_APIFLAGS & dwXmlFlags) & (HPC_APIFLAGS & dwFlags))) {
  237. goto NextHack;
  238. }
  239. // compare the file name strings for ...Private...() functions.
  240. if(pszFile) {
  241. pszBufHack = CopyStrToBuf(pArgv[HPC_ORD_FILE],
  242. szBufHack,
  243. sizeof(szBufHack)/sizeof(CHAR));
  244. // if it doesn't match the hack filename, check next hack
  245. if(strcmp(pszBufApp, pszBufHack) &&
  246. !WOW32_strstr(pszBufApp, pszBufHack)) {
  247. goto NextHack;
  248. }
  249. }
  250. // if section strings don't match...
  251. if(WOW32_stricmp((CHAR *)pszSection, pArgv[HPC_ORD_SECTION])) {
  252. goto NextHack;
  253. }
  254. // if key strings match -- we've found our hack
  255. if(!WOW32_stricmp((CHAR *)pszKey, pArgv[HPC_ORD_KEY])) {
  256. goto FoundHack;
  257. }
  258. // else see if multiple keys are specified in the XML
  259. else if(dwXmlFlags & HPC_MULTIKEY) {
  260. // if so, go get them
  261. LPSTR *argv;
  262. int i, argc;
  263. LPSTR psz;
  264. psz = malloc_w(strlen(pArgv[HPC_ORD_KEY])+1);
  265. if(NULL == psz) {
  266. return(ul);
  267. }
  268. strcpy(psz, pArgv[HPC_ORD_KEY]);
  269. argv = parsemulti(psz, &argc);
  270. if(!argv || argc <= 1) {
  271. WOW32ASSERTMSG((FALSE),
  272. ("\nWOW::ProfileHacks:Too few multikeys\n"));
  273. free_w(psz);
  274. goto NextHack;
  275. }
  276. // check each key specified
  277. for(i = 0; i < argc; i++) {
  278. // if we found a match, move on
  279. if(!WOW32_stricmp((CHAR *)pszKey, argv[i])) {
  280. free_w(argv);
  281. free_w(psz);
  282. goto FoundHack;
  283. }
  284. }
  285. free_w(argv);
  286. free_w(psz);
  287. }
  288. NextHack:
  289. // adjust to the next set of hacks...
  290. pArgv += HPC_ORD_LAST;
  291. }
  292. // if we find a matching hack spec, return the original ul.
  293. if(i == cNumHacks) {
  294. return(ul);
  295. }
  296. // If we get this far, the File, Section, and Key names all match
  297. // so this is the hack we're interested in ... so exit the loop.
  298. FoundHack:
  299. // Now determine what we want to do for the hack
  300. // Use the default value passed by the app?
  301. if(dwXmlFlags & HPC_USEDEFAULT) {
  302. // if it is a string function....
  303. if(dwFlags & HPC_STRFUNCTION) {
  304. if(cbRetBuf == 0) {
  305. strcpy(pRetBuf, pDefault);
  306. } else {
  307. strncpy(pRetBuf, pDefault, cbRetBuf);
  308. pRetBuf[cbRetBuf-1] = '\0';
  309. }
  310. if(dwXmlFlags & HPC_UPPERCASE) {
  311. WOW32_strupr(pRetBuf);
  312. }
  313. else if(dwXmlFlags & HPC_LOWERCASE) {
  314. WOW32_strlwr(pRetBuf);
  315. }
  316. return((ULONG)strlen(pRetBuf));
  317. }
  318. // else if it's an int function....
  319. else if(dwFlags & HPC_INTFUNCTION) {
  320. return((ULONG)iDefault);
  321. }
  322. }
  323. // else if we need to convert the return value to a short path
  324. else if(dwXmlFlags & HPC_CONVERTTOSHORTPATH) {
  325. // if cbRetBuf is 0, we need to return the len of the long path since
  326. // it will get copied into the buffer before we shorten it.
  327. if(cbRetBuf == 0) {
  328. return(ul);
  329. }
  330. // only do it if it is a string function....
  331. if(dwFlags & HPC_STRFUNCTION) {
  332. ul = GetShortPathName(pRetBuf, pRetBuf, cbRetBuf);
  333. }
  334. return(ul);
  335. }
  336. // else use the hack value supplied in the XML
  337. else if(dwXmlFlags & HPC_RETURNHACKVALUE) {
  338. // if it is a string function....
  339. if(dwFlags & HPC_STRFUNCTION) {
  340. // See commented out "szMCIQTW[]=" code et al in thunk for
  341. // WK32GetPrivateProfileString()
  342. if(dwXmlFlags & HPC_HASENVIRONMENTVAR) {
  343. int len;
  344. // get str of the form: "%windir%\system\file.ini" from the XML
  345. strcpy(szBufHack, pArgv[HPC_ORD_NEWDATA]);
  346. len = ExpandEnvironmentStrings(pArgv[HPC_ORD_NEWDATA],
  347. szBufHack,
  348. MAX_PATH);
  349. if(len > MAX_PATH) {
  350. WOW32ASSERTMSG((FALSE), ("\nWOW::ProfileHacks:XML new data field too long\n"));
  351. return(ul);
  352. }
  353. if(cbRetBuf == 0) {
  354. strcpy(pRetBuf, pszBufHack);
  355. } else {
  356. strncpy(pRetBuf, pszBufHack, cbRetBuf);
  357. pRetBuf[cbRetBuf-1] = '\0';
  358. }
  359. if(dwXmlFlags & HPC_UPPERCASE) {
  360. WOW32_strupr(pRetBuf);
  361. }
  362. else if(dwXmlFlags & HPC_LOWERCASE) {
  363. WOW32_strlwr(pRetBuf);
  364. }
  365. return((ULONG)strlen(pRetBuf));
  366. }
  367. else {
  368. if(cbRetBuf == 0) {
  369. strcpy(pRetBuf, pArgv[HPC_ORD_NEWDATA]);
  370. } else {
  371. strncpy(pRetBuf, pArgv[HPC_ORD_NEWDATA], cbRetBuf);
  372. pRetBuf[cbRetBuf-1] = '\0';
  373. }
  374. return((ULONG)strlen(pRetBuf));
  375. }
  376. }
  377. // else if it's an int function....
  378. else if(dwFlags & HPC_INTFUNCTION) {
  379. return(AsciiToHex(pArgv[HPC_ORD_NEWDATA]));
  380. }
  381. }
  382. // if we get to here something is amiss....
  383. WOW32ASSERTMSG((FALSE),("WOW::ProfileHacks:Incorrect Flags!\n"));
  384. return(ul);
  385. }
  386. ULONG FASTCALL WK32WritePrivateProfileString(PVDMFRAME pFrame)
  387. {
  388. ULONG ul;
  389. PSZ pszSection;
  390. PSZ pszKey;
  391. PSZ pszValue;
  392. PSZ pszFilename;
  393. register PWRITEPRIVATEPROFILESTRING16 parg16;
  394. BOOL fIsWinIni;
  395. CHAR szLowercase[MAX_PATH];
  396. GETARGPTR(pFrame, sizeof(WRITEPRIVATEPROFILESTRING16), parg16);
  397. GETPSZPTR(parg16->f1, pszSection);
  398. GETPSZPTR(parg16->f2, pszKey);
  399. GETPSZPTR(parg16->f3, pszValue);
  400. GETPSZPTR(parg16->f4, pszFilename);
  401. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  402. strncpy(szLowercase, pszFilename, MAX_PATH);
  403. szLowercase[MAX_PATH-1] = '\0';
  404. WOW32_strlwr(szLowercase);
  405. fIsWinIni = IS_WIN_INI(szLowercase);
  406. // Trying to install or change default printer to fax printer?
  407. if (fIsWinIni &&
  408. pszSection &&
  409. pszKey &&
  410. pszValue &&
  411. !WOW32_stricmp(pszSection, szDevices) &&
  412. IsFaxPrinterWriteProfileString(pszSection, pszKey, pszValue)) {
  413. ul = TRUE;
  414. goto Done;
  415. }
  416. ul = GETBOOL16( DPM_WritePrivateProfileString(
  417. pszSection,
  418. pszKey,
  419. pszValue,
  420. pszFilename
  421. ));
  422. if( ul != 0 &&
  423. fIsWinIni &&
  424. IS_EMBEDDING_SECTION( pszSection ) &&
  425. pszKey != NULL &&
  426. pszValue != NULL ) {
  427. UpdateClassesRootSubKey( pszKey, pszValue);
  428. }
  429. Done:
  430. FREEPSZPTR(pszSection);
  431. FREEPSZPTR(pszKey);
  432. FREEPSZPTR(pszValue);
  433. FREEPSZPTR(pszFilename);
  434. FREEARGPTR(parg16);
  435. return ul;
  436. }
  437. ULONG FASTCALL WK32WriteProfileString(PVDMFRAME pFrame)
  438. {
  439. ULONG ul;
  440. PSZ pszSection;
  441. PSZ pszKey;
  442. PSZ pszValue;
  443. register PWRITEPROFILESTRING16 parg16;
  444. GETARGPTR(pFrame, sizeof(WRITEPROFILESTRING16), parg16);
  445. GETPSZPTR(parg16->f1, pszSection);
  446. GETPSZPTR(parg16->f2, pszKey);
  447. GETPSZPTR(parg16->f3, pszValue);
  448. // For WinFax Lite install hack. Bug #126489 See wow32fax.c
  449. if(!gbWinFaxHack) {
  450. // Trying to install or change default printer to fax printer?
  451. if (pszSection &&
  452. pszKey &&
  453. pszValue &&
  454. !WOW32_stricmp(pszSection, szDevices) &&
  455. IsFaxPrinterWriteProfileString(pszSection, pszKey, pszValue)) {
  456. ul = TRUE;
  457. goto Done;
  458. }
  459. } else {
  460. IsFaxPrinterWriteProfileString(pszSection, pszKey, pszValue);
  461. }
  462. ul = GETBOOL16( DPM_WriteProfileString(
  463. pszSection,
  464. pszKey,
  465. pszValue
  466. ));
  467. if( ( ul != 0 ) &&
  468. IS_EMBEDDING_SECTION( pszSection ) &&
  469. ( pszKey != NULL ) &&
  470. ( pszValue != NULL ) ) {
  471. UpdateClassesRootSubKey( pszKey, pszValue);
  472. }
  473. Done:
  474. FREEPSZPTR(pszSection);
  475. FREEPSZPTR(pszKey);
  476. FREEPSZPTR(pszValue);
  477. FREEARGPTR(parg16);
  478. return ul;
  479. }
  480. ULONG FASTCALL WK32GetProfileString(PVDMFRAME pFrame)
  481. {
  482. ULONG ul;
  483. int len;
  484. PSZ pszdef;
  485. PSZ pszSection;
  486. PSZ pszKey;
  487. PSZ pszDefault;
  488. PSZ pszReturnBuffer;
  489. UINT cchMax;
  490. #ifdef FE_SB
  491. PSZ pszTmp = NULL;
  492. #endif // FE_SB
  493. register PGETPROFILESTRING16 parg16;
  494. GETARGPTR(pFrame, sizeof(GETPROFILESTRING16), parg16);
  495. GETPSZPTR(parg16->f1, pszSection);
  496. GETPSZPTR(parg16->f2, pszKey);
  497. GETPSZPTR(parg16->f3, pszDefault);
  498. ALLOCVDMPTR(parg16->f4, parg16->f5, pszReturnBuffer);
  499. cchMax = INT32(parg16->f5);
  500. #ifdef FE_SB
  501. //
  502. // For those applications that expect sLongDate contains
  503. // windows 3.1J picture format string.
  504. //
  505. if (GetSystemDefaultLangID() == 0x411 &&
  506. !lstrcmpi(pszSection, "intl") && !lstrcmpi(pszKey, "sLongDate")) {
  507. pszTmp = pszKey;
  508. pszKey = "sLongDate16";
  509. }
  510. #endif // FE_SB
  511. if (IS_EMBEDDING_SECTION( pszSection ) &&
  512. !WasSectionRecentlyUpdated() ) {
  513. if( pszKey == NULL ) {
  514. UpdateEmbeddingAllKeys();
  515. } else {
  516. UpdateEmbeddingKey( pszKey );
  517. }
  518. SetLastTimeUpdated();
  519. } else if (pszSection &&
  520. pszKey &&
  521. !WOW32_stricmp(pszSection, szDevices) &&
  522. IsFaxPrinterSupportedDevice(pszKey)) {
  523. ul = GETINT16(GetFaxPrinterProfileString(pszSection, pszKey, pszDefault, pszReturnBuffer, cchMax));
  524. goto FlushAndReturn;
  525. }
  526. // Win 3.1 & Win 9x strip trailing white space chars differently than NT.
  527. // We'll force the issue by cleaning up the default string *before* we call
  528. // GetProfileString().
  529. len = W31_w9x_MyStrLen(pszDefault);
  530. if(len) {
  531. pszdef = malloc_w(len+1);
  532. if(pszdef) {
  533. RtlCopyMemory(pszdef, pszDefault, len);
  534. pszdef[len] = '\0';
  535. }
  536. else {
  537. pszdef = pszDefault;
  538. }
  539. }
  540. else {
  541. pszdef = pszDefault;
  542. }
  543. ul = GETINT16(DPM_GetProfileString(
  544. pszSection,
  545. pszKey,
  546. pszdef,
  547. pszReturnBuffer,
  548. cchMax));
  549. //
  550. // Win3.1/Win95 compatibility: Zap the first trailing blank in pszdef
  551. // with null, but only if the default string was returned. To detect
  552. // the default string being returned we need to ignore trailing blanks.
  553. //
  554. // This code is duplicated in thunks for GetProfileString and
  555. // GetPrivateProfileString, update both if you make changes.
  556. //
  557. if ( pszdef && pszKey ) {
  558. int n, nLenDef;
  559. //
  560. // Is the default the same as the returned string up to any NULLs?
  561. //
  562. nLenDef = 0;
  563. n=0;
  564. while (
  565. (pszdef[nLenDef] == pszReturnBuffer[n]) &&
  566. pszReturnBuffer[n]
  567. ) {
  568. n++;
  569. nLenDef++;
  570. }
  571. //
  572. // Did we get out of the loop because we're at the end of the returned string?
  573. //
  574. if ( '\0' != pszReturnBuffer[n] ) {
  575. //
  576. // No. The strings are materially different - fall out.
  577. //
  578. }
  579. else {
  580. //
  581. // Ok, the strings are identical to the end of the returned string.
  582. // Is the default string spaces out to the end?
  583. //
  584. while ( ' ' == pszdef[nLenDef] ) {
  585. nLenDef++;
  586. }
  587. //
  588. // The last thing was not a space. If it was a NULL, then the app
  589. // passed in a string with trailing NULLs as default. (Otherwise
  590. // the two strings are materially different and we do nothing.)
  591. //
  592. if ( '\0' == pszdef[nLenDef] ) {
  593. char szBuf[4]; // Some random, small number of chars to get.
  594. // If the string is long, we'll get only 3 chars
  595. // (and NULL), but so what? - we only need to know if
  596. // we got a default last time...
  597. //
  598. // The returned string is the same as the default string
  599. // without trailing blanks, but this might be coincidence,
  600. // so see if a call with empty pszdef returns anything.
  601. // If it does, we don't zap because the default isn't
  602. // being used.
  603. //
  604. if (0 == DPM_GetProfileString(pszSection, pszKey, "", szBuf, sizeof(szBuf))) {
  605. //
  606. // Zap first trailing blank in pszdef with null.
  607. //
  608. pszdef[ul] = 0;
  609. FLUSHVDMPTR(parg16->f3 + ul, 1, pszdef + ul);
  610. }
  611. }
  612. }
  613. }
  614. if( CURRENTPTD()->dwWOWCompatFlags2 & WOWCF2_HACKPROFILECALL) {
  615. ul = ProfileHacks(HPC_GETPROFILESTRING | HPC_STRFUNCTION,
  616. NULL,
  617. pszSection,
  618. pszKey,
  619. pszdef,
  620. 0,
  621. pszReturnBuffer,
  622. cchMax,
  623. ul);
  624. }
  625. FlushAndReturn:
  626. #ifdef FE_SB
  627. if ( pszTmp )
  628. pszKey = pszTmp;
  629. if (CURRENTPTD()->dwWOWCompatFlagsFE & WOWCF_FE_USEUPPER) { // for WinWrite
  630. if (pszSection && !lstrcmpi(pszSection, "windows") &&
  631. pszKey && !lstrcmpi(pszKey, "device")) {
  632. CharUpper(pszReturnBuffer);
  633. }
  634. if (pszSection && !lstrcmpi(pszSection, "devices") && pszKey) {
  635. CharUpper(pszReturnBuffer);
  636. }
  637. }
  638. #endif // FE_SB
  639. if(pszdef && pszdef != pszDefault) {
  640. free_w(pszdef);
  641. }
  642. FLUSHVDMPTR(parg16->f4, (ul + (pszSection && pszKey) ? 1 : 2), pszReturnBuffer);
  643. FREEPSZPTR(pszSection);
  644. FREEPSZPTR(pszKey);
  645. FREEPSZPTR(pszDefault);
  646. FREEVDMPTR(pszReturnBuffer);
  647. FREEARGPTR(parg16);
  648. RETURN(ul);
  649. }
  650. ULONG FASTCALL WK32GetPrivateProfileString(PVDMFRAME pFrame)
  651. {
  652. ULONG ul;
  653. int len;
  654. PSZ pszdef;
  655. PSZ pszSection;
  656. PSZ pszKey;
  657. PSZ pszDefault;
  658. PSZ pszReturnBuffer;
  659. PSZ pszFilename;
  660. UINT cchMax;
  661. #ifdef FE_SB
  662. PSZ pszTmp = NULL;
  663. #endif // FE_SB
  664. register PGETPRIVATEPROFILESTRING16 parg16;
  665. CHAR szLowercase[MAX_PATH];
  666. GETARGPTR(pFrame, sizeof(GETPRIVATEPROFILESTRING16), parg16);
  667. GETPSZPTR(parg16->f1, pszSection);
  668. GETPSZPTR(parg16->f2, pszKey);
  669. GETPSZPTR(parg16->f3, pszDefault);
  670. ALLOCVDMPTR(parg16->f4, parg16->f5, pszReturnBuffer);
  671. GETPSZPTR(parg16->f6, pszFilename);
  672. // PC3270 (Personal communications): while installing this app it calls
  673. // GetPrivateProfileString (sectionname, NULL, defaultbuffer, returnbuffer,
  674. // cch = 0, filename). On win31 this call returns relevant data in return
  675. // buffer and corresponding size as return value. On NT, since the
  676. // buffersize(cch) is '0' no data is copied into the return buffer and
  677. // return value is zero which makes this app abort installation.
  678. //
  679. // So restricted compatibility:
  680. // if above is the case set
  681. // cch = 64k - offset of returnbuffer;
  682. //
  683. // A safer 'cch' would be
  684. // cch = GlobalSize(selector of returnbuffer) -
  685. // (offset of returnbuffer);
  686. // - nanduri
  687. if (!(cchMax = INT32(parg16->f5))) {
  688. if (pszKey == (PSZ)NULL) {
  689. if (pszReturnBuffer != (PSZ)NULL) {
  690. cchMax = 0xffff - (LOW16(parg16->f4));
  691. }
  692. }
  693. }
  694. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  695. strncpy(szLowercase, pszFilename, MAX_PATH);
  696. szLowercase[MAX_PATH-1] = '\0';
  697. WOW32_strlwr(szLowercase);
  698. if (IS_WIN_INI( szLowercase )) {
  699. #ifdef FE_SB
  700. //
  701. // For those applications that expect sLongDate contains
  702. // windows 3.1J picture format string.
  703. //
  704. if (GetSystemDefaultLangID() == 0x411 &&
  705. lstrcmpi( pszSection, "intl") == 0 &&
  706. lstrcmpi( pszKey, "sLongDate") == 0) {
  707. pszTmp = pszKey;
  708. pszKey = "sLongDate16";
  709. }
  710. #endif // FE_SB
  711. if (IS_EMBEDDING_SECTION( pszSection ) &&
  712. !WasSectionRecentlyUpdated() ) {
  713. if( pszKey == NULL ) {
  714. UpdateEmbeddingAllKeys();
  715. } else {
  716. UpdateEmbeddingKey( pszKey );
  717. }
  718. SetLastTimeUpdated();
  719. } else if (pszSection &&
  720. pszKey &&
  721. !WOW32_stricmp(pszSection, szDevices) &&
  722. IsFaxPrinterSupportedDevice(pszKey)) {
  723. ul = GETINT16(GetFaxPrinterProfileString(pszSection, pszKey, pszDefault, pszReturnBuffer, cchMax));
  724. goto FlushAndReturn;
  725. }
  726. }
  727. // Win 3.1 & Win 9x strip trailing white space chars differently than NT.
  728. // We'll force the issue by cleaning up the default string *before* we call
  729. // GetProfileString().
  730. len = W31_w9x_MyStrLen(pszDefault);
  731. if(len) {
  732. pszdef = malloc_w(len+1);
  733. if(pszdef) {
  734. RtlCopyMemory(pszdef, pszDefault, len);
  735. pszdef[len] = '\0';
  736. }
  737. else {
  738. pszdef = pszDefault;
  739. }
  740. }
  741. else {
  742. pszdef = pszDefault;
  743. }
  744. ul = GETUINT16(DPM_GetPrivateProfileString(
  745. pszSection,
  746. pszKey,
  747. pszdef,
  748. pszReturnBuffer,
  749. cchMax,
  750. pszFilename));
  751. // start comaptibility hacks
  752. //
  753. // Win3.1/Win95 compatibility: Zap the first trailing blank in pszDefault
  754. // with null, but only if the default string was returned. To detect
  755. // the default string being returned we need to ignore trailing blanks.
  756. //
  757. // This code is duplicated in thunks for GetProfileString and
  758. // GetPrivateProfileString, update both if you make changes.
  759. //
  760. if ( pszdef && pszKey ) {
  761. int n, nLenDef;
  762. //
  763. // Is the default the same as the returned string up to any NULLs?
  764. //
  765. nLenDef = 0;
  766. n=0;
  767. while (
  768. (pszdef[nLenDef] == pszReturnBuffer[n]) &&
  769. pszReturnBuffer[n]
  770. ) {
  771. n++;
  772. nLenDef++;
  773. }
  774. //
  775. // Did we get out of the loop because we're at the end of the returned string?
  776. //
  777. if ( '\0' != pszReturnBuffer[n] ) {
  778. //
  779. // No. The strings are materially different - fall out.
  780. //
  781. }
  782. else {
  783. //
  784. // Ok, the strings are identical to the end of the returned string.
  785. // Is the default string spaces out to the end?
  786. //
  787. while ( ' ' == pszdef[nLenDef] ) {
  788. nLenDef++;
  789. }
  790. //
  791. // The last thing was not a space. If it was a NULL, then the app
  792. // passed in a string with trailing NULLs as default. (Otherwise
  793. // the two strings are materially different and we do nothing.)
  794. //
  795. if ( '\0' == pszdef[nLenDef] ) {
  796. char szBuf[4]; // Some random, small number of chars to get.
  797. // If the string is long, we'll get only 3 chars
  798. // (and NULL), but so what? - we only need to know if
  799. // we got a default last time...
  800. //
  801. // The returned string is the same as the default string
  802. // without trailing blanks, but this might be coincidence,
  803. // so see if a call with empty pszdef returns anything.
  804. // If it does, we don't zap because the default isn't
  805. // being used.
  806. //
  807. if (0 == DPM_GetPrivateProfileString(pszSection, pszKey, "", szBuf, sizeof(szBuf), pszFilename)) {
  808. //
  809. // Zap first trailing blank in pszdef with null.
  810. //
  811. pszdef[ul] = 0;
  812. FLUSHVDMPTR(parg16->f3 + ul, 1, pszdef + ul);
  813. }
  814. }
  815. }
  816. }
  817. if( CURRENTPTD()->dwWOWCompatFlags2 & WOWCF2_HACKPROFILECALL) {
  818. ul = ProfileHacks(HPC_GETPRIVATEPROFILESTRING | HPC_STRFUNCTION,
  819. pszFilename,
  820. pszSection,
  821. pszKey,
  822. pszdef,
  823. 0,
  824. pszReturnBuffer,
  825. cchMax,
  826. ul);
  827. }
  828. /******************************************************************************
  829. This was replaced by above:
  830. if( CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_SAYITSNOTTHERE) {
  831. // CrossTalk 2.2 gets hung in a loop while trying to match a printer in
  832. // their xtalk.ini file with a printer name in the PrintDlg listbox.
  833. // There is a bug in their code for handling this that gets exposed by
  834. // the fact that NT PrintDlg listboxes do not include the port name as
  835. // Win3.1 & Win'95 do. We avoid the buggy code altogether with this
  836. // hack by telling them that the preferred printer isn't stored in
  837. // xtalk.ini. See bug #43168 a-craigj
  838. // Repro: net use lpt2: \\netprinter\share, start app, File\Print Setup
  839. // Maximizer 5.0 has similar problem. it tries to parse
  840. // print driver location however, allocates too small buffer. See
  841. // Whistler bug 288491
  842. if(!WOW32_stricmp(pszSection, "Printer")) {
  843. if((WOW32_strstr(szLowercase, "xtalk.ini") && !WOW32_stricmp(pszKey, "Device")) || // CrossTalk 2.2
  844. (WOW32_strstr(szLowercase, "bclwdde.ini") && !WOW32_stricmp(pszKey, "Driver")) ){ // Maximizer 5
  845. // We can't use strncpy here. See how cchmax is calculated
  846. // above. If we get a cchmax based on the end of the selector,
  847. // we will cause more damage with a strncpy(dst,src, cchmax)
  848. // because strncpy() NULL fills out to n. strcpy at least stops
  849. // at the first null it encounters.
  850. strcpy(pszReturnBuffer, pszdef);
  851. ul = strlen(pszReturnBuffer);
  852. }
  853. }
  854. }
  855. if( CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_SAYITSNOTTHERE) {
  856. // WHISTLER RAID BUG # 379253 05/06/2001 - alexsm
  857. // National Geographic Explorer needed the oppisite of the above. The app
  858. // was checking for a QTWVideo string, which contained a path to a quicktime
  859. // driver. Without the key, the app wouldn't play video. It's not really a
  860. // SAYITSNOTTHERE, more of a SAYITISTHERE, but this saves on compat bits.
  861. if(!WOW32_stricmp(pszSection, "mci")) {
  862. if((WOW32_strstr(szLowercase, "system.ini") && !WOW32_stricmp(pszKey, "QTWVideo"))) {
  863. DWORD cbWindir;
  864. CHAR szMCIQTW[] = "\\system\\mciqtw.drv";
  865. CHAR szQTWVideo[MAX_PATH + sizeof(szMCIQTW) / sizeof(CHAR)]; // make sure there's room for the new string (max_path + pszMCIQTW)
  866. cbWindir = GetSystemWindowsDirectory(szQTWVideo, MAX_PATH);
  867. if((cbWindir == 0) ||
  868. (cbWindir > MAX_PATH-(strlen(szMCIQTW)+1/sizeof(CHAR)))) {
  869. ul = cbWindir;
  870. pszReturnBuffer[0] = '\0';
  871. goto FlushAndReturn;
  872. }
  873. strcat(szQTWVideo, szMCIQTW);
  874. // We can't use strncpy here. See how cchmax is calculated
  875. // above. If we get a cchmax based on the end of the selector,
  876. // we will cause more damage with a strncpy(dst,src, cchmax)
  877. // because strncpy() NULL fills out to n. strcpy at least stops
  878. // at the first null it encounters.
  879. strcpy(pszReturnBuffer, szQTWVideo);
  880. ul = strlen(szQTWVideo);
  881. }
  882. }
  883. }
  884. *******************************************************************************/
  885. FlushAndReturn:
  886. #ifdef FE_SB
  887. if ( pszTmp )
  888. pszKey = pszTmp;
  889. #endif // FE_SB
  890. if (ul) {
  891. FLUSHVDMPTR(parg16->f4, (ul + (pszSection && pszKey) ? 1 : 2), pszReturnBuffer);
  892. LOGDEBUG(8,("GetPrivateProfileString returns '%s'\n", pszReturnBuffer));
  893. }
  894. #ifdef DEBUG
  895. //
  896. // Check for bad return on retrieving entire section by walking
  897. // the section making sure it's full of null-terminated strings
  898. // with an extra null at the end. Also ensure that this all fits
  899. // within the buffer.
  900. //
  901. if (!pszKey) {
  902. PSZ psz;
  903. //
  904. // We don't want to complain if the poorly-formed buffer was the one
  905. // passed in as pszDefault by the caller.
  906. //
  907. // Although the api docs clearly state that pszDefault should never
  908. // be null but win3.1 is nice enough to still deal with this. Delphi is
  909. // passing pszDefault as NULL and this following code causes an
  910. // assertion in WOW. So added the pszDefault check first.
  911. //
  912. // sudeepb 11-Sep-1995
  913. if (!pszdef || WOW32_strcmp(pszReturnBuffer, pszdef)) {
  914. psz = pszReturnBuffer;
  915. while (psz < (pszReturnBuffer + ul + 2) && *psz) {
  916. psz += strlen(psz) + 1;
  917. }
  918. WOW32ASSERTMSGF(
  919. psz < (pszReturnBuffer + ul + 2),
  920. ("GetPrivateProfileString of entire section returns poorly formed buffer.\n"
  921. "pszReturnBuffer = %p, return value = %d\n",
  922. pszReturnBuffer,
  923. ul
  924. ));
  925. }
  926. }
  927. #endif // DEBUG
  928. if(pszdef && pszdef != pszDefault) {
  929. free_w(pszdef);
  930. }
  931. FREEPSZPTR(pszSection);
  932. FREEPSZPTR(pszKey);
  933. FREEPSZPTR(pszDefault);
  934. FREEVDMPTR(pszReturnBuffer);
  935. FREEPSZPTR(pszFilename);
  936. FREEARGPTR(parg16);
  937. RETURN(ul);
  938. }
  939. ULONG FASTCALL WK32GetProfileInt(PVDMFRAME pFrame)
  940. {
  941. ULONG ul;
  942. PSZ psz1;
  943. PSZ psz2;
  944. register PGETPROFILEINT16 parg16;
  945. GETARGPTR(pFrame, sizeof(GETPROFILEINT16), parg16);
  946. GETPSZPTR(parg16->f1, psz1);
  947. GETPSZPTR(parg16->f2, psz2);
  948. ul = GETWORD16(DPM_GetProfileInt(
  949. psz1,
  950. psz2,
  951. INT32(parg16->f3)
  952. ));
  953. if( CURRENTPTD()->dwWOWCompatFlags2 & WOWCF2_HACKPROFILECALL) {
  954. ul = ProfileHacks(HPC_GETPROFILEINT | HPC_INTFUNCTION,
  955. NULL,
  956. psz1,
  957. psz2,
  958. NULL,
  959. INT32(parg16->f3),
  960. NULL,
  961. 0,
  962. ul);
  963. }
  964. //
  965. // In HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics, there
  966. // are a bunch of values that define the screen appearance. You can
  967. // watch these values get updated when you go into the display control
  968. // panel applet and change the "appearance scheme", or any of the
  969. // individual elements. The win95 shell is different than win31 in that it
  970. // sticks "twips" values in there instead of pixels. These are calculated
  971. // with the following formula:
  972. //
  973. // twips = - pixels * 72 * 20 / cyPixelsPerInch
  974. //
  975. // pixels = -twips * cyPixelsPerInch / (72*20)
  976. //
  977. // So if the value is negative, it is in twips, otherwise it in pixels.
  978. // The idea is that these values are device independent. NT is
  979. // different than win95 in that we provide an Ini file mapping to this
  980. // section of the registry where win95 does not. Now, when the Lotus
  981. // Freelance Graphics 2.1 tutorial runs, it mucks around with the look
  982. // of the screen, and it changes the border width of window frames by
  983. // using SystemParametersInfo(). When it tries to restore it, it uses
  984. // GetProfileInt("Windows", "BorderWidth", <default>), which on win31
  985. // returns pixels, on win95 returns the default (no ini mapping), and
  986. // on NT returns TWIPS. Since this negative number is interpreted as
  987. // a huge UINT, then the window frames become huge. What this code
  988. // below will do is translate the number back to pixels. [neilsa]
  989. //
  990. if ((CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_PIXELMETRICS) &&
  991. !WOW32_stricmp(psz1, "Windows") &&
  992. !WOW32_stricmp(psz2, "BorderWidth") &&
  993. ((INT)ul < 0)) {
  994. HDC hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
  995. if (hDC ) {
  996. ul = (ULONG) (-(INT)ul * GetDeviceCaps(hDC, LOGPIXELSY)/(72*20));
  997. DeleteDC(hDC);
  998. }
  999. }
  1000. FREEPSZPTR(psz1);
  1001. FREEPSZPTR(psz2);
  1002. FREEARGPTR(parg16);
  1003. RETURN(ul);
  1004. }
  1005. ULONG FASTCALL WK32GetPrivateProfileSection(PVDMFRAME pFrame)
  1006. {
  1007. ULONG ul;
  1008. PSZ psz1;
  1009. PSZ psz2;
  1010. PSZ psz4;
  1011. register PGETPRIVATEPROFILESECTION16 parg16;
  1012. GETARGPTR(pFrame, sizeof(GETPRIVATEPROFILESECTION16), parg16);
  1013. GETPSZPTR(parg16->lpszSection, psz1);
  1014. GETPSZPTR(parg16->lpResult, psz2);
  1015. GETPSZPTR(parg16->lpszFile, psz4);
  1016. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  1017. ul = GETDWORD16(DPM_GetPrivateProfileSection(
  1018. psz1,
  1019. psz2,
  1020. DWORD32(parg16->cchResult),
  1021. psz4
  1022. ));
  1023. FREEPSZPTR(psz1);
  1024. FREEPSZPTR(psz2);
  1025. FREEPSZPTR(psz4);
  1026. FREEARGPTR(parg16);
  1027. RETURN(ul);
  1028. }
  1029. ULONG FASTCALL WK32GetProfileSection(PVDMFRAME pFrame)
  1030. {
  1031. ULONG ul;
  1032. PSZ psz1;
  1033. PSZ psz2;
  1034. register PGETPROFILESECTION16 parg16;
  1035. GETARGPTR(pFrame, sizeof(GETPROFILESECTION16), parg16);
  1036. GETPSZPTR(parg16->lpszSection, psz1);
  1037. GETPSZPTR(parg16->lpResult, psz2);
  1038. ul = GETDWORD16(DPM_GetProfileSection(
  1039. psz1,
  1040. psz2,
  1041. DWORD32(parg16->cchResult)
  1042. ));
  1043. FREEPSZPTR(psz1);
  1044. FREEPSZPTR(psz2);
  1045. FREEARGPTR(parg16);
  1046. RETURN(ul);
  1047. }
  1048. ULONG FASTCALL WK32WritePrivateProfileSection(PVDMFRAME pFrame)
  1049. {
  1050. ULONG ul;
  1051. PSZ psz1;
  1052. PSZ psz2;
  1053. PSZ psz3;
  1054. register PWRITEPRIVATEPROFILESECTION16 parg16;
  1055. GETARGPTR(pFrame, sizeof(WRITEPRIVATEPROFILESECTION16), parg16);
  1056. GETPSZPTR(parg16->lpszSection, psz1);
  1057. GETPSZPTR(parg16->lpKeysAndValues, psz2);
  1058. GETPSZPTR(parg16->lpszFile, psz3);
  1059. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  1060. ul = GETBOOL16(DPM_WritePrivateProfileSection(
  1061. psz1,
  1062. psz2,
  1063. psz3
  1064. ));
  1065. FREEPSZPTR(psz1);
  1066. FREEPSZPTR(psz2);
  1067. FREEPSZPTR(psz3);
  1068. FREEARGPTR(parg16);
  1069. RETURN(ul);
  1070. }
  1071. ULONG FASTCALL WK32WriteProfileSection(PVDMFRAME pFrame)
  1072. {
  1073. ULONG ul;
  1074. PSZ psz1;
  1075. PSZ psz2;
  1076. register PWRITEPROFILESECTION16 parg16;
  1077. GETARGPTR(pFrame, sizeof(WRITEPROFILESECTION16), parg16);
  1078. GETPSZPTR(parg16->lpszSection, psz1);
  1079. GETPSZPTR(parg16->lpKeysAndValues, psz2);
  1080. ul = GETBOOL16(DPM_WriteProfileSection(
  1081. psz1,
  1082. psz2
  1083. ));
  1084. FREEPSZPTR(psz1);
  1085. FREEPSZPTR(psz2);
  1086. FREEARGPTR(parg16);
  1087. RETURN(ul);
  1088. }
  1089. ULONG FASTCALL WK32GetPrivateProfileSectionNames(PVDMFRAME pFrame)
  1090. {
  1091. ULONG ul;
  1092. PSZ psz1;
  1093. PSZ psz3;
  1094. register PGETPRIVATEPROFILESECTIONNAMES16 parg16;
  1095. GETARGPTR(pFrame, sizeof(GETPRIVATEPROFILESECTIONNAMES16), parg16);
  1096. GETPSZPTR(parg16->lpszBuffer, psz1);
  1097. GETPSZPTR(parg16->lpszFile, psz3);
  1098. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  1099. ul = GETDWORD16(DPM_GetPrivateProfileSectionNames(
  1100. psz1,
  1101. DWORD32(parg16->cbBuffer),
  1102. psz3
  1103. ));
  1104. FREEPSZPTR(psz1);
  1105. FREEPSZPTR(psz3);
  1106. FREEARGPTR(parg16);
  1107. RETURN(ul);
  1108. }
  1109. /*
  1110. ULONG FASTCALL WK32GetProfileSectionNames(PVDMFRAME pFrame)
  1111. This is implemneted by krnl386 calling GetPrivateProfileSectionNames()
  1112. with the filename = "win.ini"
  1113. */
  1114. ULONG FASTCALL WK32GetPrivateProfileStruct(PVDMFRAME pFrame)
  1115. {
  1116. ULONG ul;
  1117. PSZ psz1;
  1118. PSZ psz2;
  1119. PSZ psz3;
  1120. PSZ psz5;
  1121. register PGETPRIVATEPROFILESTRUCT16 parg16;
  1122. GETARGPTR(pFrame, sizeof(GETPRIVATEPROFILESTRUCT16), parg16);
  1123. GETPSZPTR(parg16->lpszSection, psz1);
  1124. GETPSZPTR(parg16->lpszKey, psz2);
  1125. GETPSZPTR(parg16->lpStruct, psz3);
  1126. GETPSZPTR(parg16->lpszFile, psz5);
  1127. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  1128. ul = GETBOOL16(DPM_GetPrivateProfileStruct(
  1129. psz1,
  1130. psz2,
  1131. psz3,
  1132. UINT32(parg16->cbStruct),
  1133. psz5
  1134. ));
  1135. FREEPSZPTR(psz1);
  1136. FREEPSZPTR(psz2);
  1137. FREEPSZPTR(psz3);
  1138. FREEPSZPTR(psz5);
  1139. FREEARGPTR(parg16);
  1140. RETURN(ul);
  1141. }
  1142. ULONG FASTCALL WK32WritePrivateProfileStruct(PVDMFRAME pFrame)
  1143. {
  1144. ULONG ul;
  1145. PSZ psz1;
  1146. PSZ psz2;
  1147. PSZ psz3;
  1148. PSZ psz5;
  1149. register PWRITEPRIVATEPROFILESTRUCT16 parg16;
  1150. GETARGPTR(pFrame, sizeof(WRITEPRIVATEPROFILESTRUCT16), parg16);
  1151. GETPSZPTR(parg16->lpszSection, psz1);
  1152. GETPSZPTR(parg16->lpszKey, psz2);
  1153. GETPSZPTR(parg16->lpStruct, psz3);
  1154. GETPSZPTR(parg16->lpszFile, psz5);
  1155. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  1156. ul = GETBOOL16(DPM_WritePrivateProfileStruct(
  1157. psz1,
  1158. psz2,
  1159. psz3,
  1160. UINT32(parg16->cbStruct),
  1161. psz5
  1162. ));
  1163. FREEPSZPTR(psz1);
  1164. FREEPSZPTR(psz2);
  1165. FREEPSZPTR(psz3);
  1166. FREEPSZPTR(psz5);
  1167. FREEARGPTR(parg16);
  1168. RETURN(ul);
  1169. }
  1170. ULONG FASTCALL WK32GetPrivateProfileInt(PVDMFRAME pFrame)
  1171. {
  1172. ULONG ul;
  1173. PSZ psz1;
  1174. PSZ psz2;
  1175. PSZ psz4;
  1176. register PGETPRIVATEPROFILEINT16 parg16;
  1177. GETARGPTR(pFrame, sizeof(GETPRIVATEPROFILEINT16), parg16);
  1178. GETPSZPTR(parg16->f1, psz1);
  1179. GETPSZPTR(parg16->f2, psz2);
  1180. GETPSZPTR(parg16->f4, psz4);
  1181. UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
  1182. ul = GETWORD16(DPM_GetPrivateProfileInt(
  1183. psz1,
  1184. psz2,
  1185. INT32(parg16->f3),
  1186. psz4
  1187. ));
  1188. if( CURRENTPTD()->dwWOWCompatFlags2 & WOWCF2_HACKPROFILECALL) {
  1189. ul = ProfileHacks(HPC_GETPRIVATEPROFILEINT | HPC_INTFUNCTION,
  1190. psz4,
  1191. psz1,
  1192. psz2,
  1193. NULL,
  1194. INT32(parg16->f3),
  1195. NULL,
  1196. 0,
  1197. ul);
  1198. }
  1199. /******************************************************************************
  1200. This was replaced by above:
  1201. // jarbats
  1202. // sierra's setup faults overwriting video/sound buffer
  1203. // limits. by returning videospeed as non-existent
  1204. // we force it to use the default videospeed path,not the optimized
  1205. // "bad" path code.
  1206. // this is matching with setup.exe in the registry which is not specific
  1207. // enough. post-beta2 enhance matching process to match version resources
  1208. if((CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_SAYITSNOTTHERE) &&
  1209. (!WOW32_stricmp(psz4, "sierra.ini") || WOW32_strstr(psz4, "sierra.ini")))
  1210. {
  1211. if(!WOW32_stricmp(psz1,"Config") && !WOW32_stricmp(psz2,"VideoSpeed")) {
  1212. ul = parg16->f3;
  1213. }
  1214. // King's Quest VI will go into the lame multi-media code for fullscreen
  1215. // which tries to fool apps into thinking they're running "full screen"
  1216. // in a small window on the desktop. It works unless the apps try to
  1217. // get the screen size & then use that in calculations in conjunction
  1218. // with metrics it gets from the "full screen" window. Things go south
  1219. // pretty fast fromn there. Bug #427155.
  1220. else if(!WOW32_stricmp(psz1,"info") &&
  1221. !WOW32_stricmp(psz2,"movieplayer")) {
  1222. ul = 0; // return 0 instead of 1. "movieplayer=1" in sierra.ini
  1223. }
  1224. }
  1225. *******************************************************************************/
  1226. FREEPSZPTR(psz1);
  1227. FREEPSZPTR(psz2);
  1228. FREEPSZPTR(psz4);
  1229. FREEARGPTR(parg16);
  1230. RETURN(ul);
  1231. }
  1232. ULONG FASTCALL WK32GetModuleFileName(PVDMFRAME pFrame)
  1233. {
  1234. ULONG ul;
  1235. PSZ psz2;
  1236. register PGETMODULEFILENAME16 parg16;
  1237. HANDLE hT;
  1238. GETARGPTR(pFrame, sizeof(GETMODULEFILENAME16), parg16);
  1239. ALLOCVDMPTR(parg16->f2, parg16->f3, psz2);
  1240. //
  1241. // ShellExecute DDE returns (HINST)33 when DDE is used
  1242. // to satisfy a request. This looks like a task alias
  1243. // to ISTASKALIAS but it's not.
  1244. //
  1245. if ( ISTASKALIAS(parg16->f1) && 33 != parg16->f1) {
  1246. ul = GetHtaskAliasProcessName(parg16->f1,psz2,INT32(parg16->f3));
  1247. } else {
  1248. hT = (parg16->f1 && (33 != parg16->f1))
  1249. ? (HMODULE32(parg16->f1))
  1250. : GetModuleHandle(NULL) ;
  1251. ul = GETINT16(GetModuleFileName(hT, psz2, INT32(parg16->f3)));
  1252. }
  1253. FLUSHVDMPTR(parg16->f2, strlen(psz2)+1, psz2);
  1254. FREEVDMPTR(psz2);
  1255. FREEARGPTR(parg16);
  1256. RETURN(ul);
  1257. }
  1258. ULONG FASTCALL WK32WOWFreeResource(PVDMFRAME pFrame)
  1259. {
  1260. ULONG ul;
  1261. register PWOWFREERESOURCE16 parg16;
  1262. GETARGPTR(pFrame, sizeof(*parg16), parg16);
  1263. ul = GETBOOL16(FreeResource(
  1264. HCURSOR32(parg16->f1)
  1265. ));
  1266. FREEARGPTR(parg16);
  1267. RETURN(ul);
  1268. }
  1269. ULONG FASTCALL WK32GetDriveType(PVDMFRAME pFrame)
  1270. {
  1271. ULONG ul;
  1272. CHAR RootPathName[] = "?:\\";
  1273. register PGETDRIVETYPE16 parg16;
  1274. GETARGPTR(pFrame, sizeof(GETDRIVETYPE16), parg16);
  1275. // Form Root path
  1276. RootPathName[0] = (CHAR)('A'+ parg16->f1);
  1277. ul = DPM_GetDriveType (RootPathName);
  1278. // bugbug - temporariy fixed, should be removed when base changes
  1279. // its return value for non-exist drives
  1280. // Windows 3.0 sdk manaul said this api should return 1
  1281. // if the drive doesn't exist. Windows 3.1 sdk manual said
  1282. // this api should return 0 if it failed. Windows 3.1 winfile.exe
  1283. // expects 0 for noexisting drives. The NT WIN32 API uses
  1284. // 3.0 convention. Therefore, we reset the value to zero
  1285. // if it is 1.
  1286. if (ul <= 1)
  1287. ul = 0;
  1288. // DRIVE_CDROM and DRIVE_RAMDISK are not supported under Win 3.1
  1289. if ( ul == DRIVE_CDROM ) {
  1290. ul = DRIVE_REMOTE;
  1291. }
  1292. if ( ul == DRIVE_RAMDISK ) {
  1293. ul = DRIVE_FIXED;
  1294. }
  1295. FREEARGPTR(parg16);
  1296. RETURN(ul);
  1297. }
  1298. /* WK32TermsrvGetWindowsDir - Front end to TermsrvGetWindowDirectory.
  1299. *
  1300. *
  1301. * Entry - pszPath - Pointer to return buffer for path (ascii)
  1302. * usPathLen - Size of path buffer (bytes)
  1303. *
  1304. * Exit
  1305. * SUCCESS
  1306. * True
  1307. *
  1308. * FAILURE
  1309. * False
  1310. *
  1311. */
  1312. ULONG FASTCALL WK32TermsrvGetWindowsDir(PVDMFRAME pFrame)
  1313. {
  1314. PTERMSRVGETWINDIR16 parg16;
  1315. PSTR psz;
  1316. NTSTATUS Status = 0;
  1317. USHORT usPathLen;
  1318. CHAR szWinDir[MAX_PATH];
  1319. //
  1320. // Get arguments.
  1321. //
  1322. GETARGPTR(pFrame, sizeof(TERMSRVGETWINDIR16), parg16);
  1323. psz = SEGPTR(FETCHWORD(parg16->pszPathSegment),
  1324. FETCHWORD(parg16->pszPathOffset));
  1325. usPathLen = FETCHWORD(parg16->usPathLen);
  1326. FREEARGPTR(parg16);
  1327. // Get possible long path name version
  1328. Status = GetWindowsDirectoryA(szWinDir, sizeof(szWinDir));
  1329. // If this is a long path name then get the short one
  1330. // Otherwise it will return the same path
  1331. if(Status && Status < sizeof(szWinDir)) {
  1332. Status = DPM_GetShortPathName(szWinDir, psz, (DWORD)usPathLen);
  1333. if(Status >= usPathLen) {
  1334. psz[0] = '\0';
  1335. Status = 0;
  1336. } else {
  1337. // Get the real size.
  1338. Status = lstrlen(psz);
  1339. }
  1340. }
  1341. else {
  1342. Status = 0;
  1343. }
  1344. return(NT_SUCCESS(Status));
  1345. }
  1346. // This is the strlen function that Windows 3.1 and Win 9x call from the various
  1347. // GetxxxProfileString(), and WritexxxProfilexxx() functions.
  1348. // It basically returns the length of a string sans trailing spaces and chars
  1349. // <= Carriage returns.
  1350. // See: \\papyrus\w98se\proj\win\src\CORE\KERNEL\up.c\MyStrLen()
  1351. /*
  1352. MyStrLen() {
  1353. _asm {
  1354. ; SPACE, CR, NULL never in DBCS lead byte, so we are safe here
  1355. push ax
  1356. mov cx, di ; CX = start of string
  1357. dec di
  1358. str1:
  1359. inc di
  1360. mov al, es:[di] ; Get next character
  1361. cmp al, CR
  1362. ja str1 ; Not CR or NULL
  1363. str2:
  1364. cmp di, cx ; Back at the start?
  1365. jbe str3 ; yes
  1366. dec di ; Previous character
  1367. cmp byte ptr es:[di], SPACE
  1368. je str2 ; skip spaces
  1369. inc di ; Back to CR or NULL
  1370. str3:
  1371. cmp es:[di], al
  1372. je maybe_in_code ; PMODE hack
  1373. mov es:[di], al ; Zap trailing spaces
  1374. maybe_in_code:
  1375. neg cx ; Calculate length
  1376. add cx, di
  1377. pop ax
  1378. }}
  1379. */
  1380. int W31_w9x_MyStrLen(LPSTR lpstr)
  1381. {
  1382. int len = 0;
  1383. char c;
  1384. LPSTR lpStart = lpstr;
  1385. if((lpstr == NULL) || (*lpstr == '\0')) {
  1386. return(0);
  1387. }
  1388. // look for first char <= CR (including NULL)
  1389. // SPACE, CR, NULL never in DBCS lead byte, so we are safe here
  1390. while(*lpstr > '\r') {
  1391. len++;
  1392. lpstr++;
  1393. }
  1394. c = *lpstr; // save char <= CR or NULL
  1395. // strip out any trailing spaces
  1396. while(lpstr > lpStart) {
  1397. lpstr--;
  1398. if(*lpstr != ' ') {
  1399. break;
  1400. }
  1401. len--;
  1402. }
  1403. lpStart[len] = c;
  1404. return(len);
  1405. }