TITLE USERPRO - interface to WIN.INI file include kernel.inc include pdb.inc externFP GlobalFree externFP GlobalAlloc externFP GlobalLock externFP GlobalUnlock externFP GlobalReAlloc externFP GlobalSize externFP OpenFile externFP FarMyLower ;externFP _lopen externFP _lcreat externFP _lclose externFP _lread externFP _lwrite externFP _llseek ifdef FE_SB ;Apr.26,1990 by AkiraK externFP AnsiPrev externFP FarMyIsDBCSLeadByte endif ifdef WOW externFP FarMyUpper externFP GetPrivateProfileSectionNames endif externFP TermsrvGetWindowsDir DataBegin externB szUserPro externB fBooting externW cBytesWinDir externD lpWindowsDir ifndef WOW externW cBytesSysDir externD lpSystemDir else externW cBytesSys16Dir externD lpSystem16Dir endif if 0 externB fUserPro externB UserProBuf externB PrivateProBuf externW hBuffer ifndef PHILISAWEENIE externW hWBuffer externW hPBuffer endif externW hFile externD BufAddr externD lpszUserPro endif externW TopPDB ;externW MyCSDS LeftSect DB '[' ; these next two must stay together RightSect DB ']' CarRetLF DB 13,10 EquStr DB '=' externB achTermsrvWindowsDir DataEnd sBegin MISCCODE assumes CS,MISCCODE assumes DS,NOTHING assumes ES,NOTHING externNP MISCMapDStoDATA ; WOW thunks most of these APIs. ifndef WOW SECT_LEFT equ byte ptr '[' SECT_RIGHT equ byte ptr ']' CARRETURN equ byte ptr 13 LINEFEED equ byte ptr 10 SPACE equ byte ptr ' ' TAB equ byte ptr 09 CRLF equ 0A0Dh NEWRESULT equ 1 NOSECTION equ 2 NOKEY equ 4 REMOVESECTION equ 5 REMOVEKEY equ 6 PROUNKN EQU 0 ; Profile unknown PROWININI EQU 1 ; Profile WIN.INI PROPRIVATE EQU 2 ; Profile specified by app PROWASPRIVATE EQU 3 ; Buffer contains private profile data ScanTo MACRO StopAt mov al, StopAt mov cx, -1 repne scasb ENDM ScanBack MACRO StopAt std mov al, StopAt mov cx, di inc cx repne scasb inc di ; Leave pointing to StopAt cld ENDM ;-----------------------------------------------------------------------; ; SetDefaultPro ; ; ; ; Set lpszUserPro to point to WIN.INI if it is not already set ; ; to point to a private file ; ; ; ; Arguments: ; ; ; ; Returns: ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; ; ; History: ; ; ; ;-----------------------------------------------------------------------; assumes ds,code assumes es,nothing cProc SetDefaultPro, cBegin nogen cmp fUserPro, PROWASPRIVATE je SDF_SetIt cmp fUserPro, PROUNKN ; No file specified jne SDF_Done SDF_SetIt: mov ax, dataOffset szUserPro mov word ptr [lpszUserPro], ax mov word ptr [lpszUserPro+2], ds mov fUserPro, PROWININI ifndef PHILISAWEENIE mov si,[hWBuffer] mov [hBuffer],si else mov si,[hBuffer] call FreeBuffer ; free up any buffer we may have endif SDF_Done: ret cEnd nogen ;-----------------------------------------------------------------------; ; SetPrivatePro ; ; ; ; Sets lpszUserPro to point to a private file ; ; ; ; Arguments: ; ; parmD lpFile ; ; ; ; Returns: ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; ; ; History: ; ; ; ;-----------------------------------------------------------------------; assumes ds,code assumes es,nothing cProc SetPrivatePro,, parmD lpszProfile localV NewFileBuf, 80h cBegin ifndef PHILISAWEENIE mov si, [hPBuffer] mov [hBuffer], si else cmp fUserPro, PROWASPRIVATE jne SPP_SetIt endif les di,lpszProfile test fBooting,1 jnz spr_booting smov es, ss lea di, NewFileBuf mov byte ptr es:[di.opFile], 0 ; Zap junk on stack mov ax,OF_EXIST ; OF_EXIST searches path! cCall OpenFile, lea di, [di.opFile] spr_booting: lea si, [PrivateProBuf] xor cx, cx mov cl, [si.opLen] lea si, [si.opFile] sub cx, 8 cld ifndef PHILISAWEENIE test fBooting, 1 jz @F xor bl, bl ; Terminate on null call strcmpi je SPP_KeepBuffer jmps SPP_SetIt @@: endif rep cmpsb je SPP_KeepBuffer SPP_SetIt: mov si,[hBuffer] call FreeBuffer ; free up any buffer we may have SPP_KeepBuffer: mov fUserPro, PROPRIVATE mov ax, lpszProfile.off mov [lpszUserPro].off, ax mov ax, lpszProfile.sel mov [lpszUserPro].sel, ax cEnd ;-----------------------------------------------------------------------; ; ResetPrivatePro ; ; ; ; Sets lpszUserPro to point to nothing ; ; ; ; Arguments: ; ; ; ; Returns: ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; ; ; History: ; ; ; ;-----------------------------------------------------------------------; assumes ds,code assumes es,nothing cProc ResetPrivatePro, cBegin nogen mov fUserPro, PROWASPRIVATE ret cEnd nogen ;-----------------------------------------------------------------------; ; GetProfileInt ; ; ; ; Gets the integer value for the keyword field. ; ; ; ; Arguments: ; ; parmD lpApplicationName ; ; parmD lpKeyName ; ; parmW nDefault ; ; ; ; Returns: ; ; AX = nKeyValue ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; DI,SI,DS ; ; ; ; Registers Destroyed: ; ; BX,CX,DX,ES ; ; ; ; Calls: ; ; ; ; History: ; ; ; ; Sat Oct 10, 1987 04:32:04p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc GetProfileInt,, parmD section parmD keyword parmW defint cBegin cCall MISCMapDStoDATA ; point at data segment ReSetKernelDS cCall SetDefaultPro cCall GetString, ; DX:AX contains pointer to return string ; CX is the length of the string, -1 if none mov si,ax ; save pointer offset mov ax,defint ; if so, return default integer cmp cx,-1 ; was there no string? jz intdone ; if none, use default push ds ; save DS mov ds,dx ; DS:SI has string ; AtoI function, CX has count of characters, AX is result, DS:SI is string. xor ax,ax AtoI: mov dx,10 mov bl,[si] sub bl,'0' jc AtoIDone cmp bl,10 jnc AtoIDone inc si mul dx xor bh,bh add ax,bx loop AtoI AtoIdone: pop ds ; restore DS intdone: push ax call UnlockBuffer pop ax ; get result to return cEnd ;-----------------------------------------------------------------------; ; GetProfileString ; ; ; ; Returns the string for the keyword field. ; ; ; ; Arguments: ; ; parmD lpApplicationName ; ; parmD lpKeyName ; ; parmD lpDefault ; ; parmD lpReturnedString ; ; parmW nSize ; ; ; ; Returns: ; ; AX = nLength ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; DI,SI,DS ; ; ; ; Registers Destroyed: ; ; BX,CX,DX,ES ; ; ; ; Calls: ; ; ; ; History: ; ; ; ; Sat Oct 10, 1987 04:45:20p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc GetProfileString,, parmD section parmD keyword parmD defString parmD resString parmW cchMax cBegin cCall MISCMapDStoDATA ; point at data segment ReSetKernelDS cCall SetDefaultPro if KDEBUG mov dx, off_defString or dx, seg_defString ; Catch those NULL pointers jnz ok_def mkerror ERR_BADDEFAULT,,dx,dx ok_def: endif mov ax,off_keyword mov dx,seg_keyword or ax,dx jnz GPS_Normal cCall GetKeys, ; Carry if the section not found, AX has length of "string". jnc GPS_End jmps GPS_DefString GPS_Normal: cCall GetString, ; DX:AX contains pointer to return string ; CX has length, -1 if string not found cmp cx,-1 ; see if there is any string jz GPS_DefString mov SEG_defstring,dx mov OFF_defstring,ax GPS_DefString: xor ax, ax ; bug fixed. cmp SEG_defstring, 0 je GPS_End ; Save us from the GP fault les di,defString ; DI = front of string ifdef FE_SB ;Apr.26,1990 by AkiraK call strlen ; CX = strlen, di = end of string ;get last character behind terminater push si les si,defString ; SI = front of string gps_dbcs_l1: mov al,es:[si] call FarMyIsDBCSLeadByte cmc adc si,1 cmp si,di jb gps_dbcs_l1 pop si else call strlen ; CX = strlen, di = end of string mov al,es:[di-1] ; AL = last character of string endif les di,defString ; DI = front of string ; Strip off single and double quotes cmp cx,2 ; strlen < 2? jb strdone ; yes, skip mov ah,es:[di] ; AH = first character in the string cmp ah,al ; first char = last char? jnz strdone ; if no match, then no quotes cmp al,"'" jz strq cmp al,'"' jnz strdone strq: sub cx,2 ; string is really two smaller inc di ; and starts here strdone: ; CX now has length of return string, use it for copying. mov dx,cchMax dec dx cmp cx,dx jbe GPS1 mov cx,dx GPS1: push ds ; save DS push es pop ds mov si,di ; ds:si has string push cx ; save length for return les di,ResString rep movsb ; copy string mov byte ptr es:[di], 0 ; null terminate pop ax pop ds ; restore DS GPS_End: push ax call UnlockBuffer pop ax ; get length of returned string cEnd cProc GetKeys,, parmD section parmD resstr parmW cchMax cBegin xor di,di ; make sure buffer is ready call BufferInit ; DX:AX has buffer address, NULL if it didn't work. mov di,ax ; save offset or ax,dx ; see if no address ifdef FE_SB jnz skip1 jmp GetKeysNone ; if no address, done skip1: else jz GetKeysNone ; if no address, done endif dec cchMax ; Leave room for terminating null byte mov es,dx cCall FindSection,
jc GetKeysNone lds si,resstr xor dx,dx GK3: ; Key name loop mov bx,di GK3a: mov al,es:[di] ifdef FE_SB ;Apr.26,1990 by AkiraK call FarMyIsDBCSLeadByte cmc ;if the char is lead byte of DBCS, adc di,1 ; then di += 2 else di += 1 else inc di endif cmp al,'=' je GK3c cmp al,LINEFEED ; Ignore lines without = je GK3 cmp al,SECT_LEFT ; Done if it's a section header je GK4 or al,al ; or null. jnz GK3a jmps GK4 GK3c: mov di,bx GK3d: mov al,es:[di] inc di cmp al,'=' jne GK3e xor al,al GK3e: mov [si],al inc dx inc si cmp dx,cchMax jb GK3f dec si dec dx GK3f: ifdef FE_SB ;Apr.26,1990 by AkiraK call FarMyIsDBCSLeadByte jc GK3_s1 mov al,es:[di] inc di mov [si],al inc dx inc si cmp dx,cchMax jb GK3f2 dec si dec dx GK3f2: GK3_s1: endif or al,al jnz GK3d ScanTo LINEFEED jmp GK3 GetKeysNone: stc jmps GetKeysDone GK4: mov byte ptr [si], 0 ; Terminating null or dx, dx ; No extra zapping if nothing found jz GK4x ifdef FE_SB ;Apr.26,1990 by AkiraK push dx cCall AnsiPrev, mov si,ax mov byte ptr [si], 0 mov byte ptr [si+1], 0 pop dx else mov byte ptr [si-1], 0 ; [si-1] already zero unless we hit ; cchMax above in which case, we must ; zap the previous character. endif GK4x: mov ax,dx clc GetKeysDone: cEnd ; Scan through buffer, looking for section. cProc FindSection, parmD section cBegin SS1: cmp byte ptr es:[di],SECT_LEFT ; see if it's a section header jne SS2 inc di lds si,section mov bl,SECT_RIGHT call strcmpi ; case insensitive compare je SSfound ; terminate on SECT_RIGHT SS2: ScanTo LINEFEED cmp byte ptr es:[di], 0 jne SS1 ; If it gets here, there wasn't a match. stc ; Fail jmps SSdone SSfound: ScanTo LINEFEED ; read to beginning of first keyline clc ; Success SSdone: cEnd cProc FindKey, parmD keyword cBegin mov ax, SEG_keyword or ax, OFF_keyword ; Do we have something to look for? jz FK_NoMatch FK_Next: mov al,es:[di] or al,al jz FK_NoMatch cmp al,SECT_LEFT jz FK_NoMatch lds si,keyword mov bl,'=' ; term on =. call strcmpi ; case insensitive compare, term on 0 je FK_Found ; es:di has result string ScanTo LINEFEED jmp FK_Next FK_NoMatch: stc jmps FK_Done FK_Found: clc FK_Done: cEnd cProc GetString,, parmD section parmD key cBegin xor di,di ; make sure buffer is ready call BufferInit ; DX:AX has buffer address, NULL if it didn't work. mov di,ax ; save offset or ax,dx ; see if no address jz NoMatch ; no address, nothing to match against mov es,dx ; DX:DI now has the buffer address, buffer is locked down. cCall FindSection,
; Look for the section jc NoMatch cCall FindKey, jnc HaveKey NoMatch: mov cx,-1 ; string was not found jmps GetStrDone ; if it gets here, it matched HaveKey: inc di ; pointing at = mov dx,es mov bx,di ScanTo CARRETURN ; traverse string until reach end inc cx inc cx neg cx ; will now contain string length mov ax,bx GetStrDone: cEnd ; make sure the buffer has been filled public BufferInit ; this is for the debugger BufferInit: assumes DS,CODE mov ax,[hBuffer] or ax,ax jnz bf0 xor dx,dx ret bf0: call LockBuffer mov bx,ax or bx,dx jz bf1 ret bf1: mov bx,GA_MODIFY ; make block not discardable cCall GlobalReAlloc, mov ax,di les dx, lpszUserPro cmp fUserPro, PROPRIVATE jne bf1a1 mov bx,codeOffset PrivateProBuf ; Private ie not WIN.INI cCall OpenFile, cmp ax, -1 ; File not found? jne bf1a2 or di, di jz bf1a2 ; Don't create if we want to read it. mov ax, di or ax, OF_CREATE ; Writing it, create it silently. les dx, lpszUserPro mov bx,codeOffset PrivateProBuf jmps bf1a bf1a1: or di,di jz bf1a0 or ax,OF_CREATE bf1a0: mov bx,codeOffset UserProBuf cmp byte ptr [bx],0 jz bf1a mov dx,dataOffset szUserPro and ax,NOT OF_CREATE or ax,OF_REOPEN or OF_PROMPT bf1a: cCall OpenFile, bf1a2: mov [hFile],ax inc ax jnz @F jmp bf3 ; if file not found, return 0:0 @@: mov ax,0002h call Rewind2 ; seek to end of file add ax,3 ; tack on room for cr,lf and 0 adc dx,0 jz bf1aa ; ok if less than 64k mov ax, -1 ; Limit memory used xor dx, dx bf1aa: push ax ; Length to read mov bx,GA_ZEROINIT regptr LONGINT,DX,AX cCall GlobalReAlloc, ; global block pop bx ; Stand on our head to preserve length or ax,ax jz bf3 mov hBuffer, ax push bx call LockBuffer call Rewind ; rewind to beginning of file les bx,[BufAddr] mov es:[bx],2020h ; space space pop cx ; read in the whole file sub cx, 3 ; don't fill extra space in the buffer jcxz bf1zz ; Don't bother if nothing to read cCall _lread, inc ax jz bf2 dec ax mov cx,ax ; cx has file size bf1zz: cmp cx,2 jae bf1z mov cx,2 bf1z: jmps PackBuffer bf2: call UnlockBuffer FreeBuffer: xor ax,ax mov dx,GA_DISCARDABLE shl 8 OR GA_MODIFY cCall GlobalReAlloc, xor ax,ax mov dx,(GA_SHAREABLE) shl 8 OR GA_MOVEABLE cCall GlobalReAlloc, bf3: xor ax,ax xor dx,dx mov word ptr [BufAddr][0],ax mov word ptr [BufAddr][2],dx ret public packbuffer PackBuffer: push ds mov dx,di les di,[BufAddr] lds si,[BufAddr] pb1: ifdef FE_SB ;Apr.26,1990 by AkiraK ;TAB or SPACE are never found in lead byte of DBCS. ;so, this loop is safe in DBCS. endif jcxz pb9 ; while leading space or tab mov bx, di ; Initialize first valid character lodsb dec cx cmp al, SPACE ; remove leading spaces jz pb1 cmp al, TAB ; and tabs jz pb1 dec si ; refetch last character inc cx pb2: lodsb dec cx or dx,dx ; Are we writing? jnz pb20 ; Yes, leave comments in cmp al,';' ; No, is this a comment? jne pb20 ; No, continue jcxz pb9 ; if done pb2loop: ifdef FE_SB ;Apr.26,1990 by AkiraK ;LINEFEED is never found in lead byte of DBCS. ;so, this loop is safe in DBCS. endif lodsb dec cx jz pb9 ; if done cmp al, LINEFEED ; if end of line, go on jz pb1 jmps pb2loop pb20: stosb ; first character of line ifdef FE_SB ;Apr.26,1990 by AkiraK call FarMyIsDBCSLeadByte jc pb_dbcs_s1 movsb dec cx jz pb9 pb_dbcs_s1: endif cmp al,'=' ; if '=', then end of left hand side jz pb2a jcxz pb9 cmp al, SPACE ; if space, might be trailing space jz pb2 cmp al, TAB jz pb2 cmp al, LINEFEED ; if end of line, go on jz pb1 mov bx,di ; ow save last valid character+1 jmp pb2 pb2a: mov di,bx ; remove trailing spaces on left stosb ; resave '=' pb3: ; now work on right hand side jcxz pb9 ; while leading space or tab lodsb ; remove leading spaces dec cx cmp al, SPACE jz pb3 ; and tabs cmp al, TAB jz pb3 dec si ; refetch last character inc cx pb5: ifdef FE_SB ;Apr.26,1990 by AkiraK ;LINEFEED is never found in lead byte of DBCS. ;so, this loop is safe in DBCS. endif lodsb stosb ; store character dec cx jz pb9 cmp al, LINEFEED ; at end of line? jz pb1 ; yes, go on jmp pb5 pb9: or di, di jz pb9a ; NOTHING THERE!! dec di ; remove trailing ^Z's cmp byte ptr es:[di],"Z"-"@" jz pb9 inc di pb9a: mov ax,CRLF stosw ; make sure there is a final xor ax,ax ; CARRETURN and NULL stosb pop ds ; restore DS mov si,[hBuffer] cCall GlobalUnlock, xor ax,ax regptr xsize,ax,di cCall GlobalReAlloc, public lockbuffer LockBuffer: mov si,ax cCall GlobalLock, mov word ptr BufAddr[0],ax mov word ptr BufAddr[2],dx ret public unlockbuffer UnlockBuffer: mov si,hBuffer cCall GlobalUnlock, xor ax,ax mov dx,(GA_MODIFY + (GA_DISCARDABLE SHL 8)) ; make block discardable cCall GlobalReAlloc, mov bx,-1 xchg bx,[hFile] inc bx jz ulbdone dec bx cCall _lclose, ; close file ulbdone: ret Rewind: xor ax,ax ; rewind the tape Rewind2: xor cx,cx cCall _llseek, ret ; this proc calculates the length of the string pointed to by es:di ; and returns it in cx. It searches for a CR and then backs thru any ; trailing spaces. ; it uses cx, es, and di public strlen strlen PROC NEAR ifdef FE_SB ;Apr.26,1990 by AkiraK ; Space, Carridge Return, NULL are never in lead byte of DBCS. ; So, we don't need to enable here. endif push ax ; Save ax mov cx,di ; cx = start of string dec di str1: inc di ; Search for CR or NULL mov al,es:[di] ; AL has CR or NULL cmp al,CARRETURN ja str1 str2: dec di ; Remove trailing blanks cmp di,cx ; Check for start of string jb str3 cmp byte ptr es:[di],SPACE jz str2 str3: inc di ; Restore CR or NULL cmp es:[di],al jz maybe_in_code mov es:[di],al maybe_in_code: neg cx add cx,di pop ax ; Restore ax ret strlen ENDP public strcmpi strcmpi PROC NEAR ; es:di and ds:si have strings ; es:di should be terminated by the char in bl ; ds:si is null terminated ifdef FE_SB ;Apr.26,1990 by AkiraK sti_l1: mov al,es:[di] cmp al,bl jz sti_s1 call FarMyLower mov cl,al mov al,ds:[si] call FarMyLower inc si inc di cmp al,cl jnz sti_exit call FarMyIsDBCSLeadByte jc sti_l1 mov al,es:[di] cmp al,ds:[si] jnz sti_exit inc si inc di jmp short sti_l1 sti_exit: ret sti_s1: mov al,ds:[si] or al,al ret else stci10: mov al,es:[di] cmp al,bl ; At the end? jnz stci15 ; yes, get out of here. mov al,[si] ; are we at the end of the string or al,al jmps stciex stci15: call FarMyLower stci30: mov cl,[si] xchg al,cl call FarMyLower xchg cl,al stci40: inc si inc di cmp al,cl ; Still matching chars? jz stci10 ; Yes, go try the next char. stciex: ret endif strcmpi ENDP ;-----------------------------------------------------------------------; ; WriteProfileString ; ; ; ; Copies the given character string to WIN.INI. ; ; ; ; Arguments: ; ; parmD lpApplicationName ; ; parmD lpKeyName ; ; parmD lpString ; ; ; ; Returns: ; ; AX = bResult ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; DI,SI,DS ; ; ; ; Registers Destroyed: ; ; BX,CX,DX,ES ; ; ; ; Calls: ; ; ; ; History: ; ; ; ; Sat Oct 10, 1987 05:12:51p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc WriteProfileString,, parmD section parmD keyword parmD result localD ptrTmp localW WhatIsMissing localW nBytes localW fh cBegin cCall MISCMapDStoDATA ; point at data segment ReSetKernelDS cCall SetDefaultPro ;make sure buffer is ready mov si,[hBuffer] call FreeBuffer ; free up any buffer we may have cmp ax,SEG_section jne WPS0 cmp ax,SEG_keyword jne WPS0 cmp ax,SEG_result jne WPS0 jmp WriteDone WPS0: mov di,2 ; write call BufferInit ; read in a fresh copy ; DX:AX has buffer address, NULL if it didn't work mov di,ax or ax,dx jnz WPS1 jmp WriteDone WPS1: push dx ; save buffer selector cCall GlobalSize, ; how big is he? or dx, dx ; more than 64k, icky jnz WPS_TooBig cmp ax, 0FF00h ; more than 64K-256, icky jb WPS_SmallEnough WPS_TooBig: pop ax ; throw away saved buffer selector xor ax, ax ; return FALSE if file too big jmp WriteDone WPS_SmallEnough: pop es ; selector of buffer popped into es push ds call Rewind ; ES:DI now has the buffer address, buffer is locked down ; scan through buffer, looking for section cCall FindSection,
jc WPS5 mov ax, SEG_keyword or ax, OFF_keyword jnz WPS2 mov WhatIsMissing, REMOVESECTION ScanBack SECT_LEFT jmps WPS9 WPS2: cCall FindKey, jnc WPS7 ; if it gets here, there wasn't a match mov WhatIsMissing,NOKEY jmps WPS8 ; if it gets here, there wasn't a match WPS5: mov WhatIsMissing,NOSECTION jmps WPS8 WPS7: inc di ; di now points to result mov WhatIsMissing,NEWRESULT mov ax, SEG_result or ax, OFF_result jnz WPS9 ; NEWRESULT ScanBack LINEFEED inc di ; Now points to the keyword jmps WPS9 WPS8: cmp WhatIsMissing,NEWRESULT jz WPS9 WPS14: ; get rid of extra CRLF or di, di jz WPS9 dec di mov al,es:[di] cmp al,CARRETURN jz WPS14 cmp al,LINEFEED jz WPS14 add di,3 WPS9: ; write out up to here in file pop ds push ds mov bx,[hFile] cmp bx,-1 jnz WPS10 lds dx,lpszUserPro ; create win.ini xor cx,cx ; no special attributes cCall _lcreat, ; create the file pop ds push ds mov [hFile],ax mov bx,ax ; bx has file handle inc ax jz WPSError ; -1 means didn't work xor dx,dx cCall _lwrite, ; Zero length write to reset file or ax,ax jz WPS10 ; size on a network file (3.0 bug) WPSError: pop ds call UnlockBuffer xor ax,ax jmp WriteDone WPS10: mov bx,[hFile] mov fh,bx ; save file handle in local variable xor cx,cx mov nBytes,cx ; write file mov off_ptrTmp,di mov seg_ptrTmp,es mov cx,di ; cx has file size push es pop ds xor dx,dx call WriteCheck ; write and check the write cmp WhatIsMissing,NOSECTION jnz WPS11 mov ax, SEG_keyword ; Wanted to delete it? or ax, OFF_keyword jnz WPS10a jmp WPS13 ; Yes, don't do anything WPS10a: pop ds push ds mov dx,codeOffset CarRetLF mov cx,2 call WriteCheck mov dx,codeOffset LeftSect mov cx,1 call WriteCheck les di,section call strlen lds dx,section call WriteCheck pop ds push ds mov dx,codeOffset RightSect mov cx,3 call WriteCheck WPS11: cmp WHatIsMissing, REMOVESECTION jne WPS11a WPS11b: ScanTo LINEFEED ; Skip Current Line WPS11c: mov al, es:[di] or al, al jz WPS13 cmp al, SECT_LEFT je WPS13 cmp al, ';' jne WPS11b ; Skip this line ; Preserve Comment lines smov ds, es ; Write from ds:dx mov dx, di ScanTo LINEFEED mov cx, di sub cx, dx call WriteCheck jmps WPS11c WPS11a: cmp WhatIsMissing,NEWRESULT jz WPS15 ; WhatIsMissing == NOKEY mov ax, SEG_result ; Delete keyword? or ax, OFF_result jz WPS13 ; Yes, do nothing since not there! les di,keyword call strlen lds dx,keyword call WriteCheck pop ds push ds mov dx,codeOffset EquStr mov cx,1 call WriteCheck jmps WPS15a ; and write out result WPS15: ; Found keyword, have new result mov ax, SEG_result or ax, OFF_result ; Have result to set? jnz WPS15a ScanTo LINEFEED ; No result, delete line jmps WPS13 WPS15a: les di,result call strlen lds dx,result call WriteCheck pop ds push ds mov dx,codeOffset CarRetLF mov cx,2 call WriteCheck WPS12: les di,ptrTmp cmp WhatIsMissing,NEWRESULT jnz WPS13 ; get rid of old result ScanTo LINEFEED WPS13: mov dx,di xor al,al mov cx,-1 repne scasb sub di,3 ; one past end, plus extra CRLF sub di,dx if 1 jbe WPS23 ; if di points before dx blow it off endif mov cx,di if 0 or cx,cx ; if <= 0 then nothing to write jle WPS23 endif mov si,dx mov dx,cx ; We are growing the file. Seek add dx,nBytes xor cx,cx ; to new EOF and set file size cCall _llseek, ; with zero length write (DOS 2.X ; BIOS bug with writes past current xor cx,cx ; EOF with DTA near end of memory) call WriteCheck mov dx,nBytes ; Now backup to write rest of file xor cx,cx cCall _llseek, push es pop ds mov cx,di mov dx,si call WriteCheck WPS23: xor cx,cx call WriteCheck pop ds call UnlockBuffer call FreeBuffer mov ax,1 WriteDone: cEnd public WriteCheck WriteCheck: cCall _lwrite, mov cx,ax inc ax jz WC1 dec ax add [nBytes],cx ret WC1: pop ax ; return address jmp WPSError ;-----------------------------------------------------------------------; ; GetPrivateProfileInt ; ; ; ; Gets the integer value for the keyword field from a private file ; ; ; ; Arguments: ; ; parmD lpApplicationName ; ; parmD lpKeyName ; ; parmW nDefault ; ; parmD lpFile ; ; ; ; Returns: ; ; AX = nKeyValue ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; DI,SI,DS ; ; ; ; Registers Destroyed: ; ; BX,CX,DX,ES ; ; ; ; Calls: ; ; ; ; History: ; ; ; ; Sat Oct 10, 1987 04:32:04p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc GetPrivateProfileInt,, parmD Section parmD keyword parmW defint parmD lpFile localV Buffer,80h cBegin cCall MISCMapDStoDATA ; Safety lea si,Buffer cCall ForcePrivatePro, cCall SetPrivatePro, cCall GetProfileInt, cCall ResetPrivatePro cEnd ;-----------------------------------------------------------------------; ; GetPrivateProfileString ; ; ; ; Returns the string for the keyword field from a private file ; ; ; ; Arguments: ; ; parmD lpApplicationName ; ; parmD lpKeyName ; ; parmD lpDefault ; ; parmD lpReturnedString ; ; parmW nSize ; ; parmD lpFile ; ; ; ; Returns: ; ; AX = nLength ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; DI,SI,DS ; ; ; ; Registers Destroyed: ; ; BX,CX,DX,ES ; ; ; ; Calls: ; ; ; ; History: ; ; ; ; Sat Oct 10, 1987 04:45:20p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc GetPrivateProfileString,, parmD section parmD keyword parmD defString parmD resString parmW cchMax parmD lpFile localV Buffer,80h cBegin cCall MISCMapDStoDATA ; Safety lea si,Buffer cCall ForcePrivatePro, cCall SetPrivatePro, cCall GetProfileString, cCall ResetPrivatePro cEnd ;-----------------------------------------------------------------------; ; WritePrivateProfileString ; ; ; ; Copies the given character string to a private file ; ; ; ; Arguments: ; ; parmD lpApplicationName ; ; parmD lpKeyName ; ; parmD lpString ; ; parmD lpFile ; ; ; ; Returns: ; ; AX = bResult ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; DI,SI,DS ; ; ; ; Registers Destroyed: ; ; BX,CX,DX,ES ; ; ; ; Calls: ; ; ; ; History: ; ; ; ; Sat Oct 10, 1987 05:12:51p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc WritePrivateProfileString,, parmD section parmD keyword parmD result parmD lpFile localV Buffer,80h cBegin cCall MISCMapDStoDATA ; Safety lea si,Buffer cCall ForcePrivatePro, cCall SetPrivatePro, cCall WriteProfileString, cCall ResetPrivatePro cEnd ;-----------------------------------------------------------------------; ; ForcePrivatePro ; ; If the file pointed to is not qualified then we force ; the file into the Windows directory. ; ; Entry: ; BX = buffer on stack ; ; Returns: ; ; Registers Destroyed: ; ; History: ; Tue 14-Nov-1989 20:30:48 -by- David N. Weise [davidw] ; Wrote it! ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc ForcePrivatePro,, parmD lpDest parmD lpSource cBegin ifdef FE_SB ;Apr.26,1990 by AkiraK cld xor ax,ax mov bx,'/' shl 8 + '\' xor dx,dx lds si,lpSource ; first get length of string mov cx,si mov al,ds:[si] call FarMyIsDBCSLeadByte jnc fpp_s1 cmp byte ptr ds:[si].1,':' ; is it qualified with a drive? jnz fpp_s1 inc dx fpp_s1: fpp_l1: lodsb or al,al jz fpp_got_length cmp al,bh jz fpp_qualified cmp al,bl jz fpp_qualified fpp_s2: call FarMyIsDBCSLeadByte jc fpp_l1 inc si jmp fpp_l1 fpp_qualified: inc dx jmp fpp_s2 else cld xor ax,ax mov bx,'/' shl 8 + '\' xor dx,dx lds si,lpSource ; first get length of string mov cx,si cmp byte ptr ds:[si].1,':' ; is it qualified with a drive? jnz @F inc dx @@: lodsb or al,al jz fpp_got_length cmp al,bh jz fpp_qualified cmp al,bl jnz @B fpp_qualified: inc dx jmp @B endif fpp_got_length: sub si,cx xchg si,cx les di,lpDest or dx,dx jnz fpp_copy_name push cx cCall MISCMapDStoDATA ResetKernelDS mov cx,cBytesWinDir lds si,lpWindowsDir rep movsb mov al,'\' stosb pop cx lds si,lpSource fpp_copy_name: rep movsb cEnd endif ; ndef WOW ;-----------------------------------------------------------------------; ; GetWindowsDirectory ; ; ; Entry: ; parmD lpBuffer pointer to buffer ; parmW cbBuffer size of buffer ; ; Returns: ; AX = size of string copied ; ; Registers Destroyed: ; ; History: ; Sun 24-Sep-1989 16:18:46 -by- David N. Weise [davidw] ; Wrote it! ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc IGetWindowsDirectory,, parmD lpBuf parmW cbBuffer cBegin cCall MISCMapDStoDATA ; point at data segment ResetKernelDS if 1 ;HYDRA ; Get the current windows directory, since it depends on the state of ini-file ; mapping (assumes lpWindowsDir already points to achCtxWindowsDir - ldboot.asm). mov si, offset achTermsrvWindowsDir cCall TermsrvGetWindowsDir, or ax, ax ; ax != 0 -> success jz short gwd_exit push es smov es,ds mov di, si ; es:di points to windows path mov cx,-1 xor ax,ax repnz scasb not cx dec cx mov cBytesWinDir, cx pop es else ; HYDRA mov cx,cBytesWinDir lds si,lpWindowsDir endif inc cx ; Room for NULL mov ax, cx cmp cx, 3 ; Just 3 bytes implies : jne gwd_notroot ifdef FE_SB ;Apr.26,1990 by AkiraK mov al,ds:[si+0] ;Make sure the 1st byte is not call FarMyIsDBCSLeadByte ; DBCS lead byte. jnc gwd_notroot endif cmp byte ptr ds:[si+1], ':' ; Make sure jne gwd_notroot inc ax ; Allow for \ gwd_notroot: cmp ax,cbBuffer ; is there enough room in buffer? ja gwd_exit dec cx ; don't copy null les di,lpBuf cld ifdef WOW ;; For WOW we might be running on a file system that supports lower case ;; however some apps can't cope with lowercase names so we uppercase it here push ax gwd_loop: lodsb ;; LATER ;; call FarMyUpper ; Convert char to UpperCase stosb ifdef FE_SB ;; call MyIsDBCSLeadByte ;; jc gwd_loop ; copy second byte in east ;; movsb endif loop gwd_loop pop ax else ; WOW rep movsb endif; WOW mov es:[di],cl dec ax cmp ax, 3 jne gwd_exit mov di, word ptr lpBuf ; Get pointer to dest again ifdef FE_SB ;Apr.26,1990 by AkiraK mov al,ds:[di+0] ;Make sure the 1st byte is not call FarMyIsDBCSLeadByte ; DBCS lead byte. jnc gwd_exit endif cmp byte ptr es:[di+1], ':' jne gwd_exit mov byte ptr es:[di+2], '\' mov byte ptr es:[di+3], cl gwd_exit: cEnd ;-----------------------------------------------------------------------; ; GetSystemDirectory ; ; Entry: ; parmD lpBuf pointer to buffer ; parmW cbBuffer size of buffer ; ; Returns: ; AX = size of string copied ; ; Registers Destroyed: ; ; History: ; Sun 24-Sep-1989 16:18:46 -by- David N. Weise [davidw] ; ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc IGetSystemDirectory,, parmD lpBuf parmW cbBuffer cBegin cCall MISCMapDStoDATA ; point at data segment ResetKernelDS ifndef WOW mov cx,cBytesSysDir lds si,lpSystemDir else mov cx,cBytesSys16Dir lds si,lpSystem16Dir endif inc cx ; Room for NULL mov ax, cx cmp cx, 3 ; Just 3 bytes implies : jne gsd_notroot ifdef FE_SB ;Apr.26,1990 by AkiraK mov al,ds:[si+0] ;Make sure the 1st byte is not call FarMyIsDBCSLeadByte ; DBCS lead byte. jnc gsd_notroot endif cmp byte ptr ds:[si+1], ':' ; Make sure jne gsd_notroot inc ax ; Allow for \ gsd_notroot: cmp ax,cbBuffer ; is there enough room in buffer? ja gsd_exit dec cx ; don't copy null les di,lpBuf cld ifdef WOW ;; For WOW we might be running on a file system that supports lower case ;; however some apps can't cope with lowercase names so we uppercase it here push ax gsd_loop: lodsb call FarMyUpper ; Convert char to UpperCase stosb ifdef FE_SB ;; call MyIsDBCSLeadByte ;; jc gsd_loop ; copy second byte in east ;; movsb endif loop gsd_loop pop ax else ; WOW rep movsb endif; WOW mov es:[di],cl dec ax ; return number of bytes in string cmp ax, 3 jne gsd_exit mov di, word ptr lpBuf ; Get pointer to dest again ifdef FE_SB ;Apr.26,1990 by AkiraK mov al,ds:[di+0] ;Make sure the 1st byte is not call FarMyIsDBCSLeadByte ; DBCS lead byte. jnc gsd_exit endif cmp byte ptr es:[di+1], ':' jne gsd_exit mov byte ptr es:[di+2], '\' mov byte ptr es:[di+3], cl gsd_exit: cEnd ;-----------------------------------------------------------------------; ; GetProfileSectionNames ; ; Entry: ; parmD lpBuf pointer to buffer for section names ; parmW cbBuffer size of buffer ; ; Returns: ; ; Registers Destroyed: ; ; History: ; ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc GetProfileSectionNames,, parmD lpBuf parmW cbBuffer cBegin cCall MISCMapDStoDATA ; point at data segment ResetKernelDS mov si, dataoffset szUserPro regptr xWinDotIni,ds,si cCall GetPrivateProfileSectionNames, cEnd sEnd MISCCODE ifndef WOW sBegin INITCODE assumes cs, CODE assumes ds, nothing assumes es, nothing szWININI db 'WININI=' lenWININI equ $-codeoffset szWININI ;-----------------------------------------------------------------------; ; SetUserPro ; ; ; ; Set szUserPro to the string given in the environment variable WININI ; ; The default is WIN.INI ; ; ; ; Arguments: ; ; ; ; Returns: ; ; ; ; Error Returns: ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; ; ; History: ; ; ; ;-----------------------------------------------------------------------; cProc SetUserPro,, cBegin SetKernelDS es mov ds, TopPDB mov ds, ds:[PDB_environ] cld xor si, si smov es,cs assumes es,CODE FindWinIni: cmp byte ptr ds:[si], 0 je EndEnv mov di, codeoffset szWININI mov cx, lenWININI rep cmpsb je FoundEntry dec si SkipEntry: lodsb or al, al jnz SkipEntry jmps FindWinIni FoundEntry: SetKernelDS es mov di, dataoffset szUserPro CopyEntry: lodsb stosb or al, al jnz CopyEntry EndEnv: assumes es, nothing cEnd sEnd INITCODE endif ; ndef WOW end