source: trunk/src/kernel32/directory.cpp@ 4562

Last change on this file since 4562 was 4526, checked in by sandervl, 25 years ago

SearchPathA fix (multiple dirs), add rename odin.ini entry for winspool.drv, extra pointer checks in Read/WriteProcessMemory

File size: 21.3 KB
Line 
1/* $Id: directory.cpp,v 1.33 2000-10-25 19:46:59 sandervl Exp $ */
2
3/*
4 * Win32 Directory functions for OS/2
5 *
6 * Copyright 1998 Sander van Leeuwen
7 *
8 * NOTE: Directory creation has to be done in install program (odin\win)
9 *
10 * Parts based on Wine code (991031) (files\directory.c)
11 *
12 * DOS directories functions
13 *
14 * Copyright 1995 Alexandre Julliard
15 *
16 * TODO:
17 * - System/window directories should be created by install program!
18 *
19 * Project Odin Software License can be found in LICENSE.TXT
20 *
21 */
22
23
24/*****************************************************************************
25 * Includes *
26 *****************************************************************************/
27
28#include <odin.h>
29#include <odinwrap.h>
30#include <os2win.h>
31#include <stdlib.h>
32#include <unicode.h>
33#include <heapstring.h>
34#include <options.h>
35#include "initterm.h"
36#include <win\file.h>
37#include <string.h>
38#include "oslibdos.h"
39#include "profile.h"
40
41#define DBG_LOCALLOG DBG_directory
42#include "dbglocal.h"
43
44ODINDEBUGCHANNEL(KERNEL32-DIRECTORY)
45
46
47/*****************************************************************************
48 * Local Prototypes *
49 *****************************************************************************/
50
51
52static char DIR_Windows[MAX_PATHNAME_LEN];
53static char DIR_System[MAX_PATHNAME_LEN];
54
55//******************************************************************************
56//******************************************************************************
57char *InternalGetWindowsDirectoryA()
58{
59 return DIR_Windows;
60}
61//******************************************************************************
62//******************************************************************************
63char *InternalGetSystemDirectoryA()
64{
65 return DIR_System;
66}
67//******************************************************************************
68//******************************************************************************
69void InitDirectories()
70{
71 char *endofwinpath, *tmp;
72 int len;
73
74 strcpy(DIR_System, kernel32Path);
75 len = strlen(DIR_System);
76 if(DIR_System[len-1] == '\\') {
77 DIR_System[len-1] = 0;
78 }
79 len = PROFILE_GetOdinIniString(ODINDIRECTORIES,"WINDOWS","",DIR_Windows,sizeof(DIR_Windows));
80 if (len > 2) {
81 if(DIR_Windows[len-1] == '\\') {
82 DIR_Windows[len-1] = 0;
83 }
84 }
85 else {
86 strcpy(DIR_Windows, DIR_System);
87 endofwinpath = tmp = strchr(DIR_Windows, '\\');
88 while(tmp) {
89 tmp = strchr(endofwinpath+1, '\\');
90 if(tmp)
91 endofwinpath = tmp;
92 }
93 if(endofwinpath) {
94 *endofwinpath = 0; //remove \SYSTEM32
95 }
96 else DebugInt3();
97 }
98}
99/*****************************************************************************
100 * Name : GetCurrentDirectoryA
101 * Purpose : query the current directory
102 * Parameters:
103 * Variables :
104 * Result :
105 * Remark : returned length is number of characters required or used for current dir
106 * *excluding* terminator
107 * Status :
108 *
109 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
110 *****************************************************************************/
111
112ODINFUNCTION2(UINT, GetCurrentDirectoryA, UINT, nBufferLength,
113 LPSTR, lpBuffer)
114{
115 UINT rc;
116
117 rc = OSLibDosQueryDir(nBufferLength, lpBuffer);
118 if(rc && rc < nBufferLength) {
119 dprintf(("CurrentDirectory = %s (%d)", lpBuffer, rc));
120 }
121 else dprintf(("CurrentDirectory returned %d", rc));
122 return rc;
123}
124
125
126/*****************************************************************************
127 * Name : GetCurrentDirectoryW
128 * Purpose : query the current directory
129 * Parameters:
130 * Variables :
131 * Result :
132 * Remark :
133 * Status :
134 *
135 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
136 *****************************************************************************/
137
138ODINFUNCTION2(UINT, GetCurrentDirectoryW, UINT, nBufferLength,
139 LPWSTR, lpBuffer)
140{
141 char *asciidir = (char *)malloc(nBufferLength+1);
142 int rc;
143
144 rc = O32_GetCurrentDirectory(nBufferLength, asciidir);
145 if(rc != 0)
146 AsciiToUnicode(asciidir, lpBuffer);
147 free(asciidir);
148 return(rc);
149}
150
151
152/*****************************************************************************
153 * Name : SetCurrentDirectoryA
154 * Purpose :
155 * Parameters:
156 * Variables :
157 * Result :
158 * Remark :
159 * Status :
160 *
161 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
162 *****************************************************************************/
163
164
165ODINFUNCTION1(BOOL, SetCurrentDirectoryA,
166 LPCSTR, lpstrDirectory)
167{
168 if(HIWORD(lpstrDirectory) == 0)
169 {
170 SetLastError(ERROR_INVALID_PARAMETER);
171 return FALSE;
172 }
173
174 // cut off trailing backslashes
175 // not if a process wants to change to the root directory
176 int len = lstrlenA(lpstrDirectory);
177 if ( ( (lpstrDirectory[len - 1] == '\\') ||
178 (lpstrDirectory[len - 1] == '/') ) &&
179 (len != 1) )
180 {
181 LPSTR lpTemp = (LPSTR)_alloca(len);
182 lstrcpynA(lpTemp,
183 lpstrDirectory,
184 len); // len is including trailing NULL!!
185 lpstrDirectory = lpTemp;
186 }
187
188 dprintf(("SetCurrentDirectoryA %s", lpstrDirectory));
189 return O32_SetCurrentDirectory((LPSTR)lpstrDirectory);
190}
191
192
193/*****************************************************************************
194 * Name : SetCurrentDirectoryW
195 * Purpose :
196 * Parameters:
197 * Variables :
198 * Result :
199 * Remark :
200 * Status :
201 *
202 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
203 *****************************************************************************/
204
205ODINFUNCTION1(BOOL,SetCurrentDirectoryW,LPCWSTR,lpPathName)
206{
207 char *asciipath;
208 BOOL rc;
209
210 asciipath = UnicodeToAsciiString((LPWSTR)lpPathName);
211 rc = SetCurrentDirectoryA(asciipath);
212 FreeAsciiString(asciipath);
213 return(rc);
214}
215
216
217/*****************************************************************************
218 * Name : CreateDirectoryA
219 * Purpose :
220 * Parameters:
221 * Variables :
222 * Result :
223 * Remark :
224 * Status :
225 *
226 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
227 *****************************************************************************/
228
229ODINFUNCTION2(BOOL, CreateDirectoryA,
230 LPCSTR, lpstrDirectory,
231 PSECURITY_ATTRIBUTES,arg2)
232{
233 int len = strlen(lpstrDirectory);
234
235 // cut off trailing backslashes
236 if ( (lpstrDirectory[len - 1] == '\\') ||
237 (lpstrDirectory[len - 1] == '/') )
238 {
239 LPSTR lpTemp = (LPSTR)_alloca(len);
240 lstrcpynA(lpTemp,
241 lpstrDirectory,
242 len ); // len is including trailing NULL!!
243 lpstrDirectory = lpTemp;
244 }
245
246 dprintf(("CreateDirectoryA %s",
247 lpstrDirectory));
248
249 // PH Note 2000/06/12:
250 // Creation of an existing directory is NO ERROR it seems.
251 DWORD dwAttr = GetFileAttributesA(lpstrDirectory);
252 if (dwAttr != -1)
253 if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
254 {
255 SetLastError(ERROR_SUCCESS);
256 return TRUE;
257 }
258
259 return(O32_CreateDirectory(lpstrDirectory,
260 arg2));
261}
262
263/*****************************************************************************
264 * Name : CreateDirectoryW
265 * Purpose :
266 * Parameters:
267 * Variables :
268 * Result :
269 * Remark :
270 * Status :
271 *
272 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
273 *****************************************************************************/
274
275ODINFUNCTION2(BOOL,CreateDirectoryW,LPCWSTR, arg1,
276 PSECURITY_ATTRIBUTES,arg2)
277{
278 BOOL rc;
279 char *astring;
280
281 astring = UnicodeToAsciiString((LPWSTR)arg1);
282 rc = CreateDirectoryA(astring, arg2);
283 FreeAsciiString(astring);
284 return(rc);
285}
286
287/*****************************************************************************
288 * Name : BOOL WIN32API CreateDirectoryExA
289 * Purpose : The CreateDirectoryExA function creates a new directory with a
290 * specified path that retains the attributes of a specified
291 * template directory. If the underlying file system supports
292 * security on files and directories, the function applies a
293 * specified security descriptor to the new directory.
294 * The new directory retains the other attributes of the specified
295 * template directory. Note that CreateDirectoryEx has a template
296 * parameter, while CreateDirectory does not.
297 * Parameters: LPCSTR lpTemplateDirectory pointer to path string of template
298 * directory
299 * LPCSTR lpNewDirectory pointer to path string of directory
300 * to create
301 * LPSECURITY_ATTRIBUTES lpSecurityAttributes pointer to security
302 * descriptor
303 *
304 * Variables :
305 * Result : If the function succeeds, the return value is nonzero.
306 * If the function fails, the return value is zero.
307 * To get extended error information, call GetLastError.
308 * Remark :
309 * Status : UNTESTED STUB
310 *
311 * Author : Markus Montkowski [Tha, 1998/05/21 17:46]
312 *****************************************************************************/
313
314BOOL WIN32API CreateDirectoryExA( LPCSTR lpTemplateDirectory,
315 LPCSTR lpNewDirectory,
316 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
317{
318
319 dprintf(("KERNEL32:CreateDirectoryExA(%08x,%08x,%08x) not properly implemented\n",
320 lpTemplateDirectory,lpNewDirectory,lpSecurityAttributes
321 ));
322
323 return CreateDirectoryA(lpNewDirectory, lpSecurityAttributes);
324}
325
326/*****************************************************************************
327 * Name : BOOL WIN32API CreateDirectoryExW
328 * Purpose : The CreateDirectoryExW function creates a new directory with a
329 * specified path that retains the attributes of a specified
330 * template directory. If the underlying file system supports
331 * security on files and directories, the function applies a
332 * specified security descriptor to the new directory.
333 * The new directory retains the other attributes of the specified
334 * template directory. Note that CreateDirectoryEx has a template
335 * parameter, while CreateDirectory does not.
336 * Parameters: LPCWSTR lpTemplateDirectory pointer to path string of template
337 * directory
338 * LPCWSTR lpNewDirectory pointer to path string of directory
339 * to create
340 * LPSECURITY_ATTRIBUTES lpSecurityAttributes pointer to security
341 * descriptor
342 *
343 * Variables :
344 * Result : If the function succeeds, the return value is nonzero.
345 * If the function fails, the return value is zero.
346 * To get extended error information, call GetLastError.
347 * Remark :
348 * Status : UNTESTED STUB
349 *
350 * Author : Markus Montkowski [Tha, 1998/05/21 17:46]
351 *****************************************************************************/
352
353BOOL WIN32API CreateDirectoryExW( LPCWSTR lpTemplateDirectory,
354 LPCWSTR lpNewDirectory,
355 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
356{
357
358 dprintf(("KERNEL32:CreateDirectoryExW(%08x,%08x,%08x) not properly implemented\n",
359 lpTemplateDirectory,lpNewDirectory,lpSecurityAttributes
360 ));
361
362 return CreateDirectoryW(lpNewDirectory, lpSecurityAttributes);
363}
364
365/*****************************************************************************
366 * Name : GetSystemDirectoryA
367 * Purpose :
368 * Parameters:
369 * Variables :
370 * Result :
371 * Remark : Should return length of system dir even if lpBuffer == NULL
372 * Status :
373 *
374 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
375 *****************************************************************************/
376
377ODINFUNCTION2(UINT,GetSystemDirectoryA,LPSTR,lpBuffer,
378 UINT,uSize)
379{
380 int len;
381 char *dir;
382
383 dir = InternalGetSystemDirectoryA();
384 len = lstrlenA(dir);
385 if(lpBuffer)
386 lstrcpynA(lpBuffer, dir, uSize);
387 return len;
388}
389
390
391/*****************************************************************************
392 * Name : GetSystemDirectoryW
393 * Purpose :
394 * Parameters:
395 * Variables :
396 * Result :
397 * Remark : Should return length of system dir even if lpBuffer == NULL
398 * Status :
399 *
400 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
401 *****************************************************************************/
402
403ODINFUNCTION2(UINT,GetSystemDirectoryW,LPWSTR,lpBuffer,
404 UINT, uSize)
405{
406 char *asciibuffer = NULL;
407 UINT rc;
408
409 if(lpBuffer)
410 asciibuffer = (char *)alloca(uSize+1);
411
412 if(lpBuffer && asciibuffer == NULL)
413 {
414 DebugInt3();
415 }
416
417 rc = GetSystemDirectoryA(asciibuffer, uSize);
418 if(rc && asciibuffer)
419 AsciiToUnicode(asciibuffer, lpBuffer);
420
421 return(rc);
422}
423
424
425/*****************************************************************************
426 * Name : GetWindowsDirectoryA
427 * Purpose :
428 * Parameters:
429 * Variables :
430 * Result :
431 * Remark : Should return length of system dir even if lpBuffer == NULL
432 * Status :
433 *
434 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
435 *****************************************************************************/
436
437ODINFUNCTION2(UINT,GetWindowsDirectoryA,LPSTR,lpBuffer,
438 UINT,uSize)
439{
440 char *dir;
441 int len;
442
443 dir = InternalGetWindowsDirectoryA();
444 len = lstrlenA(dir);
445 if(lpBuffer)
446 lstrcpynA(lpBuffer, dir, uSize);
447 return len;
448}
449
450
451/*****************************************************************************
452 * Name : GetWindowsDirectoryW
453 * Purpose :
454 * Parameters:
455 * Variables :
456 * Result :
457 * Remark : Should return length of system dir even if lpBuffer == NULL
458 * Status :
459 *
460 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
461 *****************************************************************************/
462
463ODINFUNCTION2(UINT,GetWindowsDirectoryW,LPWSTR,lpBuffer,
464 UINT, uSize)
465{
466 char *asciibuffer = NULL;
467 UINT rc;
468
469 if(lpBuffer)
470 asciibuffer = (char *)alloca(uSize+1);
471
472 if(lpBuffer && asciibuffer == NULL)
473 {
474 DebugInt3();
475 }
476
477 rc = GetWindowsDirectoryA(asciibuffer, uSize);
478 if(rc && asciibuffer)
479 AsciiToUnicode(asciibuffer, lpBuffer);
480
481 return(rc);
482}
483
484
485/*****************************************************************************
486 * Name : RemoveDirectoryA
487 * Purpose :
488 * Parameters:
489 * Variables :
490 * Result :
491 * Remark :
492 * Status :
493 *
494 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
495 *****************************************************************************/
496
497
498ODINFUNCTION1(BOOL, RemoveDirectoryA,
499 LPCSTR, lpstrDirectory)
500{
501 int len = strlen(lpstrDirectory);
502
503 // cut off trailing backslashes
504 if ( (lpstrDirectory[len - 1] == '\\') ||
505 (lpstrDirectory[len - 1] == '/') )
506 {
507 LPSTR lpTemp = (LPSTR)_alloca(len);
508 lstrcpynA(lpTemp,
509 lpstrDirectory,
510 len ); // len is including trailing NULL!!
511 lpstrDirectory = lpTemp;
512 }
513
514 dprintf(("RemoveDirectory %s",
515 lpstrDirectory));
516
517 return O32_RemoveDirectory(lpstrDirectory);
518}
519
520
521/*****************************************************************************
522 * Name : RemoveDirectoryW
523 * Purpose :
524 * Parameters:
525 * Variables :
526 * Result :
527 * Remark :
528 * Status :
529 *
530 * Author : Patrick Haller [Wed, 1999/09/28 20:44]
531 *****************************************************************************/
532
533ODINFUNCTION1(BOOL,RemoveDirectoryW,LPCWSTR,lpPathName)
534{
535 char *asciipath;
536 BOOL rc;
537
538 asciipath = UnicodeToAsciiString((LPWSTR)lpPathName);
539 rc = RemoveDirectoryA(asciipath);
540 FreeAsciiString(asciipath);
541 return(rc);
542}
543
544/***********************************************************************
545 * DIR_TryModulePath
546 *
547 * Helper function for DIR_SearchPath.
548 */
549static BOOL DIR_TryModulePath( LPCSTR name, char *full_name )
550{
551 char buffer[OFS_MAXPATHNAME];
552 LPSTR p;
553
554 if (!GetModuleFileNameA( 0, buffer, sizeof(buffer) ))
555 buffer[0]='\0';
556
557 if (!(p = strrchr( buffer, '\\' ))) return FALSE;
558 if (sizeof(buffer) - (++p - buffer) <= strlen(name)) return FALSE;
559 strcpy( p, name );
560
561 return OSLibDosSearchPath(OSLIB_SEARCHFILE, NULL, buffer, full_name, MAX_PATHNAME_LEN);
562}
563
564
565/***********************************************************************
566 * DIR_SearchPath
567 *
568 * Implementation of SearchPath32A. 'win32' specifies whether the search
569 * order is Win16 (module path last) or Win32 (module path first).
570 *
571 * FIXME: should return long path names.
572 */
573DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext,
574 char *full_name )
575{
576 DWORD len;
577 LPCSTR p;
578 LPSTR tmp = NULL;
579 BOOL ret = TRUE;
580
581 /* First check the supplied parameters */
582
583 p = strrchr( name, '.' );
584 if (p && !strchr( p, '/' ) && !strchr( p, '\\' ))
585 ext = NULL; /* Ignore the specified extension */
586 if ((*name && (name[1] == ':')) ||
587 strchr( name, '/' ) || strchr( name, '\\' ))
588 path = NULL; /* Ignore path if name already contains a path */
589 if (path && !*path) path = NULL; /* Ignore empty path */
590
591 /* See if path is a list of directories to search. If so, only search
592 those (according to SDK docs) */
593 if ((path != NULL) && strchr(path, ';')) {
594 ret = OSLibDosSearchPath(OSLIB_SEARCHDIR, (LPSTR)path, (LPSTR)name,
595 full_name, MAX_PATHNAME_LEN);
596 goto done;
597 }
598
599 len = strlen(name);
600 if (ext) len += strlen(ext);
601 if (path) len += strlen(path) + 1;
602
603 /* Allocate a buffer for the file name and extension */
604
605 if (path || ext)
606 {
607 if (!(tmp = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len + 1 )))
608 {
609 SetLastError( ERROR_OUTOFMEMORY );
610 return 0;
611 }
612 if (path)
613 {
614 strcpy( tmp, path );
615 strcat( tmp, "\\" );
616 strcat( tmp, name );
617 }
618 else strcpy( tmp, name );
619 if (ext) strcat( tmp, ext );
620 name = tmp;
621 }
622
623 /* If we have an explicit path, everything's easy */
624
625 if (path || (*name && (name[1] == ':')) ||
626 strchr( name, '/' ) || strchr( name, '\\' ))
627 {
628 ret = OSLibDosSearchPath(OSLIB_SEARCHFILE, NULL, (LPSTR)name, full_name, MAX_PATHNAME_LEN);
629 goto done;
630 }
631
632 /* Try the path of the current executable (for Win32 search order) */
633 if (DIR_TryModulePath( name, full_name )) goto done;
634
635 /* Try the current directory */
636 if (OSLibDosSearchPath(OSLIB_SEARCHCURDIR, NULL, (LPSTR)name, full_name, MAX_PATHNAME_LEN))
637 goto done;
638
639 /* Try the Windows system directory */
640 if (OSLibDosSearchPath(OSLIB_SEARCHDIR, (LPSTR)&DIR_System, (LPSTR)name, full_name, MAX_PATHNAME_LEN))
641 goto done;
642
643 /* Try the Windows directory */
644 if (OSLibDosSearchPath(OSLIB_SEARCHDIR, (LPSTR)&DIR_Windows, (LPSTR)name, full_name, MAX_PATHNAME_LEN))
645 goto done;
646
647 /* Try all directories in path */
648 ret = OSLibDosSearchPath(OSLIB_SEARCHENV, "PATH", (LPSTR)name, full_name, MAX_PATHNAME_LEN);
649
650done:
651 if (tmp) HeapFree( GetProcessHeap(), 0, tmp );
652 return ret;
653}
654
655
656/***********************************************************************
657 * SearchPath32A [KERNEL32.447]
658 *
659 * Searches for a specified file in the search path.
660 *
661 * PARAMS
662 * path [I] Path to search
663 * name [I] Filename to search for.
664 * ext [I] File extension to append to file name. The first
665 * character must be a period. This parameter is
666 * specified only if the filename given does not
667 * contain an extension.
668 * buflen [I] size of buffer, in characters
669 * buffer [O] buffer for found filename
670 * lastpart [O] address of pointer to last used character in
671 * buffer (the final '\')
672 *
673 * RETURNS
674 * Success: length of string copied into buffer, not including
675 * terminating null character. If the filename found is
676 * longer than the length of the buffer, the length of the
677 * filename is returned.
678 * Failure: Zero
679 *
680 * NOTES
681 * Should call SetLastError(but currently doesn't).
682 */
683DWORD WINAPI SearchPathA(LPCSTR path, LPCSTR name, LPCSTR ext, DWORD buflen,
684 LPSTR buffer, LPSTR *lastpart )
685{
686 char full_name[MAX_PATHNAME_LEN];
687
688 if (!DIR_SearchPath( path, name, ext, (LPSTR)full_name )) return 0;
689 lstrcpynA( buffer, (LPSTR)full_name, buflen);
690 SetLastError(0);
691 return strlen(buffer);
692}
693
694
695/***********************************************************************
696 * SearchPath32W (KERNEL32.448)
697 */
698DWORD WINAPI SearchPathW(LPCWSTR path, LPCWSTR name, LPCWSTR ext,
699 DWORD buflen, LPWSTR buffer, LPWSTR *lastpart )
700{
701 char full_name[MAX_PATHNAME_LEN];
702
703 LPSTR pathA = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
704 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
705 LPSTR extA = HEAP_strdupWtoA( GetProcessHeap(), 0, ext );
706 DWORD ret = DIR_SearchPath( pathA, nameA, extA, (LPSTR)full_name );
707 HeapFree( GetProcessHeap(), 0, extA );
708 HeapFree( GetProcessHeap(), 0, nameA );
709 HeapFree( GetProcessHeap(), 0, pathA );
710 if (!ret) return 0;
711
712 lstrcpynAtoW( buffer, full_name, buflen);
713 SetLastError(0);
714 return strlen(full_name);
715}
Note: See TracBrowser for help on using the repository browser.