So far so good. But the code, found in the Windows 3.1 version of SoftRAM's SR-START.EXE, is taken directly from copyrighted code that first appeared in PC Magazine! (This is a general pattern: SoftRAM's SOFTRAM1.386 is directly copied from Microsoft's PAGEFILE.386, SOFTRAM2.386 is directly copied from Microsoft's PAGESWAP.386, and SoftRAM's Windows 95 version of DYNAPAGE.VXD is copied directly from Microsoft's DYNAPAGE VxD.)
Here is the relevant code, disassembled from the Windows 3.1 version of SoftRAM's SR-START.EXE. I added the variable names such as _hBlks:
1.1FCC sub_0057 proc far 1.1FCC enter 7D8h,0 1.1FD0 push di 1.1FD1 push si 1.1FD2 xor si,si ; _i 1.1FD4 push si 1.1FD5 push 10272 1.1FD8 call far ptr GlobalDosAlloc 1.1FDD mov [_hBlks+2],ax 1.1FE1 mov [_hBlks],dx 1.1FE5 loc_0401: ; xref 1.200C 1.1FE5 mov di,si 1.1FE7 shl di,2 1.1FEA mov ax,[_hBlks+di] 1.1FEE or ax,[_hBlks+2+di] 1.1FF2 jz short loc_0402 1.1FF4 push 0 1.1FF6 push 10272 1.1FF9 call far ptr GlobalDosAlloc 1.1FFE inc si 1.1FFF mov di,si 1.2001 shl di,2 1.2004 mov [_hBlks+2+di],ax 1.2008 mov [_hBlks+di],dx 1.200C jmp short loc_0401 ; (1FE5) 1.200E loc_0402: ; xref 1.1FF2 1.200E xor di,di 1.2010 mov [_totBlks],si ; or _nblocks 1.2013 jmp short loc_0405 ; (2052) 1.2015 loc_0403: ; xref 1.2054 1.2015 mov bx,di 1.2017 shl bx,2 1.201A lea ax,cs:[_hBlks+2] 1.201E add bx,ax 1.2020 mov ax,[bx] 1.2022 mov dx,[bx+2] 1.2025 mov [_hb],ax 1.2028 mov [_hb-2],dx 1.202B push 2 1.202D lea ax,[_hb] 1.2030 push ax 1.2031 lea ax,[_bsel] 1.2034 push ax 1.2035 call far ptr _memcpy 1.203A add sp,6 1.203D cmp word ptr [_bsel],0 1.2041 je short loc_0404 1.2043 push word ptr [_bsel] 1.2046 push 0 1.2048 push 1 1.204A push 0 1.204C call far ptr GlobalReAlloc 1.2051 loc_0404: ; xref 1.2041 1.2051 inc di 1.2052 loc_0405: ; xref 1.2013 1.2052 cmp si,di 1.2054 jg loc_0403 1.2056 mov ax,1 1.2059 pop si 1.205A pop di 1.205B leave 1.205C retf sub_0057 endpHere is a C version of this code, prepared by someone (not me) who had not yet seen the corresponding PC Magazine code:
BOOL AllocDosMem() { unsigned nBlockCount; // [bp-2] unsigned selector; // [bp-4] DWORD temp; // [bp-6]/[bp-8] DWORD DosMemBlocks[500]; int i = 0; // in SI DosMemBlocks[0] = GlobalDosAlloc( 10272 ); // Why 10272? Why ask Why? while (DosMemBlocks[i]) DosMemBlocks[++i] = GlobalDosAlloc( 10272 ); nBlockCount = i; for ( i=0; i<nBlockCount; i++ ) { temp = DosMemBlocks[i]; memcpy( &selector, &temp, 2 ); if (selector) GlobalReAlloc( selector, 1, 0 ); } return 1; }Now, here is the original code, from John McSorley's article, "1MBFort Protects Low Memory," PC Magazine, March 28, 1995 (see 1mbfort.zip):
/**************************************************************************** 1MBFort Version 1.0 Copyright (c) 1995 John McSorley. First Published in PC Magazine, March 28, 1995, US Edition PROGRAM: 1MBFort.c PURPOSE: 1MBFort low order memory fragmenter helps prevent "Insufficient memory to start application" errors. // ...... ****************************************************************************/ // ...... void HandleWMCreate(hWnd, message, wParam, lParam) HWND hWnd; /* window handle */ UINT message; /* type of message */ WPARAM wParam; /* additional information */ LPARAM lParam; /* additional information */ { int i; int totBlks; DWORD hBlks[500]; DWORD hb; unsigned int hbret; unsigned int bsel; unsigned int isize; unsigned int nblocks; unsigned int iret; char sIniFile[255]; char appTitle[80]; /* Get users Windows Directory */ i=GetWindowsDirectory(sIniFile,254); /* Add INI filename */ strcat(sIniFile,"\\1MBFort.INI"); /* Get blocksize or default to -1 */ isize=GetPrivateProfileInt("1MBFort","BLOCKSIZE",-1 ,sIniFile); if (isize==-1) { /* No INI setting so create INI file with default value 10272 */ iret=WritePrivateProfileString("1MBFort", "INSTRUCTIONS", "Valid BlockSize values 5000 to 20000 no commas.", sIniFile); iret=WritePrivateProfileString("1MBFort", "BLOCKSIZE", "10272", sIniFile); /* Use default blocksize */ isize=10272; } else { /* Range check user supplied block size */ if (isize == 0) isize=10272; if (isize < 5000) isize=5000; if (isize > 20000) isize=20000; } /* Allocate as many memory blocks as possible */ i=0; hBlks[i]=GlobalDosAlloc(isize); while (hBlks[i]!=0) { i++; hBlks[i]=GlobalDosAlloc(isize); } totBlks=i; /* save number of blocks allocated for later display */ nblocks=totBlks; /* display resulting size/blocks */ sprintf(appTitle,"1MBFort %d/%d",isize - 32,nblocks); /* set text for task manager display */ SetWindowText(hWnd, appTitle); /* shrink blocks so that low order memory is fragmented */ for (i=0;i<=totBlks;i++) { hb=hBlks[i]; memcpy(&bsel,&hb,2); if (bsel!=0) { /* reduce blocks to as small as possible */ /* request 1 byte but will get 32 bytes due to overhead */ hbret=GlobalReAlloc(bsel,1,0); } } }In SR-START, Syncronys has merely dropped the check that the PC Magazine code does for .INI file settings, and the code that in 1MBFORT sets the window title. The rest is the same, down to the rather silly use of the C memcpy( ) function to copy two bytes!
While plagiarism is the sincerest form of flattery, the fact is that the PC Magazine code is, with all due respect, actually not all that good -- better solutions to the Windows 3.1 conventional-memory problem have been published in Microsoft Systems Journal (Matt Pietrek's BELOW1MB and FIX1MB programs). FIX1MB is available online. Here is the help text:
Fix1MB is a tool to help with the dreaded "out of memory" errors in Windows that cause new programs to be unable to start. This particular problem is caused by DLLs that inadvertantly suck up all the memory below 1 megabyte in the Windows address space. Windows needs a certain amount of memory below 1 megabyte to start a new task.(Also see Matt Pietrek's new book, Windows 95 System Programming Secrets.)
Fix1MB not only shows you which DLLs and programs are using this precious memory, it also acts to prevent them from grabbing the memory below 1 megabyte.
Fix1MB can either be run from within Windows, or loaded at startup time. The latter allows Fix1MB to preserve even more memory below 1 megabyte. The "Add FIX1MB to SYSTEM.INI" button will put Fix1MB in your SYSTEM.INI if you desire (the FIX1MB.EXE, FX1MBDLL.DLL and PROCHOOK.DLL files must be in the same directory for this to work.)
Fix1MB was written by Matt Pietrek (CIS: 71774,362), and is from his May 1995 Questions and Answers column in the Microsoft Systems Journal. Please refer to that column for additional information.